Fix/variable input validation issue (#23300)

This commit is contained in:
Matri Qi
2025-08-02 17:35:51 +08:00
committed by GitHub
parent 688d07e9c3
commit aac849d4f4
3 changed files with 75 additions and 46 deletions

View File

@@ -1,6 +1,6 @@
'use client'
import type { FC } from 'react'
import React, { useCallback } from 'react'
import React, { useCallback, useState } from 'react'
import produce from 'immer'
import { useTranslation } from 'react-i18next'
import type { OutputVar } from '../../../code/types'
@@ -9,7 +9,9 @@ import VarTypePicker from './var-type-picker'
import Input from '@/app/components/base/input'
import type { VarType } from '@/app/components/workflow/types'
import { checkKeys, replaceSpaceWithUnderscreInVarNameInput } from '@/utils/var'
import type { ToastHandle } from '@/app/components/base/toast'
import Toast from '@/app/components/base/toast'
import { useDebounceFn } from 'ahooks'
type Props = {
readonly: boolean
@@ -27,6 +29,7 @@ const OutputVarList: FC<Props> = ({
onRemove,
}) => {
const { t } = useTranslation()
const [toastHandler, setToastHandler] = useState<ToastHandle>()
const list = outputKeyOrders.map((key) => {
return {
@@ -34,6 +37,27 @@ const OutputVarList: FC<Props> = ({
variable_type: outputs[key]?.type,
}
})
const { run: validateVarInput } = useDebounceFn((existingVariables: typeof list, newKey: string) => {
const { isValid, errorKey, errorMessageKey } = checkKeys([newKey], true)
if (!isValid) {
setToastHandler(Toast.notify({
type: 'error',
message: t(`appDebug.varKeyError.${errorMessageKey}`, { key: errorKey }),
}))
return
}
if (existingVariables.some(key => key.variable?.trim() === newKey.trim())) {
setToastHandler(Toast.notify({
type: 'error',
message: t('appDebug.varKeyError.keyAlreadyExists', { key: newKey }),
}))
}
else {
toastHandler?.clear?.()
}
}, { wait: 500 })
const handleVarNameChange = useCallback((index: number) => {
return (e: React.ChangeEvent<HTMLInputElement>) => {
const oldKey = list[index].variable
@@ -41,22 +65,8 @@ const OutputVarList: FC<Props> = ({
replaceSpaceWithUnderscreInVarNameInput(e.target)
const newKey = e.target.value
const { isValid, errorKey, errorMessageKey } = checkKeys([newKey], true)
if (!isValid) {
Toast.notify({
type: 'error',
message: t(`appDebug.varKeyError.${errorMessageKey}`, { key: errorKey }),
})
return
}
if (list.map(item => item.variable?.trim()).includes(newKey.trim())) {
Toast.notify({
type: 'error',
message: t('appDebug.varKeyError.keyAlreadyExists', { key: newKey }),
})
return
}
toastHandler?.clear?.()
validateVarInput(list.toSpliced(index, 1), newKey)
const newOutputs = produce(outputs, (draft) => {
draft[newKey] = draft[oldKey]
@@ -64,8 +74,7 @@ const OutputVarList: FC<Props> = ({
})
onChange(newOutputs, index, newKey)
}
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [list, onChange, outputs, outputKeyOrders])
}, [list, onChange, outputs, outputKeyOrders, validateVarInput])
const handleVarTypeChange = useCallback((index: number) => {
return (value: string) => {
@@ -75,7 +84,6 @@ const OutputVarList: FC<Props> = ({
})
onChange(newOutputs)
}
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [list, onChange, outputs, outputKeyOrders])
const handleVarRemove = useCallback((index: number) => {

View File

@@ -1,6 +1,6 @@
'use client'
import type { FC } from 'react'
import React, { useCallback, useMemo } from 'react'
import React, { useCallback, useMemo, useState } from 'react'
import { useTranslation } from 'react-i18next'
import produce from 'immer'
import RemoveButton from '../remove-button'
@@ -9,11 +9,13 @@ import Input from '@/app/components/base/input'
import type { ValueSelector, Var, Variable } from '@/app/components/workflow/types'
import { VarType as VarKindType } from '@/app/components/workflow/nodes/tool/types'
import { checkKeys, replaceSpaceWithUnderscreInVarNameInput } from '@/utils/var'
import type { ToastHandle } from '@/app/components/base/toast'
import Toast from '@/app/components/base/toast'
import { ReactSortable } from 'react-sortablejs'
import { v4 as uuid4 } from 'uuid'
import { RiDraggable } from '@remixicon/react'
import cn from '@/utils/classnames'
import { useDebounceFn } from 'ahooks'
type Props = {
nodeId: string
@@ -39,6 +41,7 @@ const VarList: FC<Props> = ({
isSupportFileVar = true,
}) => {
const { t } = useTranslation()
const [toastHandle, setToastHandle] = useState<ToastHandle>()
const listWithIds = useMemo(() => list.map((item) => {
const id = uuid4()
@@ -48,27 +51,35 @@ const VarList: FC<Props> = ({
}
}), [list])
const { run: validateVarInput } = useDebounceFn((list: Variable[], newKey: string) => {
const { isValid, errorKey, errorMessageKey } = checkKeys([newKey], true)
if (!isValid) {
setToastHandle(Toast.notify({
type: 'error',
message: t(`appDebug.varKeyError.${errorMessageKey}`, { key: errorKey }),
}))
return
}
if (list.some(item => item.variable?.trim() === newKey.trim())) {
console.log('new key', newKey.trim())
setToastHandle(Toast.notify({
type: 'error',
message: t('appDebug.varKeyError.keyAlreadyExists', { key: newKey }),
}))
}
else {
toastHandle?.clear?.()
}
}, { wait: 500 })
const handleVarNameChange = useCallback((index: number) => {
return (e: React.ChangeEvent<HTMLInputElement>) => {
replaceSpaceWithUnderscreInVarNameInput(e.target)
const newKey = e.target.value
const { isValid, errorKey, errorMessageKey } = checkKeys([newKey], true)
if (!isValid) {
Toast.notify({
type: 'error',
message: t(`appDebug.varKeyError.${errorMessageKey}`, { key: errorKey }),
})
return
}
if (list.map(item => item.variable?.trim()).includes(newKey.trim())) {
Toast.notify({
type: 'error',
message: t('appDebug.varKeyError.keyAlreadyExists', { key: newKey }),
})
return
}
toastHandle?.clear?.()
validateVarInput(list.toSpliced(index, 1), newKey)
onVarNameChange?.(list[index].variable, newKey)
const newList = produce(list, (draft) => {
@@ -76,7 +87,7 @@ const VarList: FC<Props> = ({
})
onChange(newList)
}
}, [list, onVarNameChange, onChange])
}, [list, onVarNameChange, onChange, validateVarInput])
const handleVarReferenceChange = useCallback((index: number) => {
return (value: ValueSelector | string, varKindType: VarKindType, varInfo?: Var) => {