feat: add input field variables change sync

This commit is contained in:
twwu 2025-05-28 16:38:49 +08:00
parent 769b5e185a
commit cc7ad5ac97
6 changed files with 63 additions and 14 deletions

View File

@ -6,11 +6,12 @@ import { useCallback } from 'react'
import { useTranslation } from 'react-i18next' import { useTranslation } from 'react-i18next'
import type { InputVar } from '@/models/pipeline' import type { InputVar } from '@/models/pipeline'
import type { FormData } from './form/types' import type { FormData } from './form/types'
import type { MoreInfo } from '@/app/components/workflow/types'
type InputFieldEditorProps = { type InputFieldEditorProps = {
show: boolean show: boolean
onClose: () => void onClose: () => void
onSubmit: (data: InputVar) => void onSubmit: (data: InputVar, moreInfo?: MoreInfo) => void
initialData?: InputVar initialData?: InputVar
} }
@ -23,9 +24,9 @@ const InputFieldEditor = ({
const { t } = useTranslation() const { t } = useTranslation()
const formData = convertToInputFieldFormData(initialData) const formData = convertToInputFieldFormData(initialData)
const handleSubmit = useCallback((value: FormData) => { const handleSubmit = useCallback((value: FormData, moreInfo?: MoreInfo) => {
const inputFieldData = convertFormDataToINputField(value) const inputFieldData = convertFormDataToINputField(value)
onSubmit(inputFieldData) onSubmit(inputFieldData, moreInfo)
onClose() onClose()
}, [onSubmit, onClose]) }, [onSubmit, onClose])

View File

@ -18,13 +18,15 @@ import ActionButton from '@/app/components/base/action-button'
type FieldItemProps = { type FieldItemProps = {
readonly?: boolean readonly?: boolean
payload: InputVar payload: InputVar
index: number
onClickEdit: (id: string) => void onClickEdit: (id: string) => void
onRemove: (id: string) => void onRemove: (index: number) => void
} }
const FieldItem = ({ const FieldItem = ({
readonly, readonly,
payload, payload,
index,
onClickEdit, onClickEdit,
onRemove, onRemove,
}: FieldItemProps) => { }: FieldItemProps) => {
@ -40,8 +42,8 @@ const FieldItem = ({
const handleRemove = useCallback(() => { const handleRemove = useCallback(() => {
if (readonly) return if (readonly) return
onRemove(payload.variable) onRemove(index)
}, [onRemove, payload.variable, readonly]) }, [index, onRemove, readonly])
return ( return (
<div <div

View File

@ -12,7 +12,7 @@ type FieldListContainerProps = {
className?: string className?: string
inputFields: InputVar[] inputFields: InputVar[]
onListSortChange: (list: SortableItem[]) => void onListSortChange: (list: SortableItem[]) => void
onRemoveField: (id: string) => void onRemoveField: (index: number) => void
onEditField: (id: string) => void onEditField: (id: string) => void
readonly?: boolean readonly?: boolean
} }
@ -46,6 +46,7 @@ const FieldListContainer = ({
{inputFields?.map((item, index) => ( {inputFields?.map((item, index) => (
<FieldItem <FieldItem
key={index} key={index}
index={index}
readonly={readonly} readonly={readonly}
payload={item} payload={item}
onRemove={onRemoveField} onRemove={onRemoveField}

View File

@ -6,13 +6,28 @@ import {
import { produce } from 'immer' import { produce } from 'immer'
import type { InputVar } from '@/models/pipeline' import type { InputVar } from '@/models/pipeline'
import type { SortableItem } from './types' import type { SortableItem } from './types'
import type { MoreInfo, ValueSelector } from '@/app/components/workflow/types'
import { ChangeType } from '@/app/components/workflow/types'
import { useWorkflow } from '@/app/components/workflow/hooks'
import { useBoolean } from 'ahooks'
export const useFieldList = ( export const useFieldList = (
initialInputFields: InputVar[], initialInputFields: InputVar[],
onInputFieldsChange: (value: InputVar[]) => void, onInputFieldsChange: (value: InputVar[]) => void,
nodeId: string,
) => { ) => {
const [inputFields, setInputFields] = useState<InputVar[]>(initialInputFields) const [inputFields, setInputFields] = useState<InputVar[]>(initialInputFields)
const inputFieldsRef = useRef<InputVar[]>(inputFields) const inputFieldsRef = useRef<InputVar[]>(inputFields)
const [removedVar, setRemovedVar] = useState<ValueSelector>([])
const [removedIndex, setRemoveIndex] = useState(0)
const { handleOutVarRenameChange, isVarUsedInNodes, removeUsedVarInNodes } = useWorkflow()
const [isShowRemoveVarConfirm, {
setTrue: showRemoveVarConfirm,
setFalse: hideRemoveVarConfirm,
}] = useBoolean(false)
const handleInputFieldsChange = useCallback((newInputFields: InputVar[]) => { const handleInputFieldsChange = useCallback((newInputFields: InputVar[]) => {
setInputFields(newInputFields) setInputFields(newInputFields)
inputFieldsRef.current = newInputFields inputFieldsRef.current = newInputFields
@ -38,12 +53,27 @@ export const useFieldList = (
setEditingField(undefined) setEditingField(undefined)
}, []) }, [])
const handleRemoveField = useCallback((id: string) => { const handleRemoveField = useCallback((index: number) => {
const newInputFields = inputFieldsRef.current.filter(field => field.variable !== id) const itemToRemove = inputFieldsRef.current[index]
// Check if the variable is used in other nodes
if (isVarUsedInNodes([nodeId, itemToRemove.variable || ''])) {
showRemoveVarConfirm()
setRemovedVar([nodeId, itemToRemove.variable || ''])
setRemoveIndex(index as number)
return
}
const newInputFields = inputFieldsRef.current.splice(index, 1)
handleInputFieldsChange(newInputFields) handleInputFieldsChange(newInputFields)
}, [handleInputFieldsChange]) }, [handleInputFieldsChange, isVarUsedInNodes, nodeId, showRemoveVarConfirm])
const handleSubmitField = useCallback((data: InputVar) => { const onRemoveVarConfirm = useCallback(() => {
const newInputFields = inputFieldsRef.current.splice(removedIndex, 1)
handleInputFieldsChange(newInputFields)
removeUsedVarInNodes(removedVar)
hideRemoveVarConfirm()
}, [removedIndex, handleInputFieldsChange, removeUsedVarInNodes, removedVar, hideRemoveVarConfirm])
const handleSubmitField = useCallback((data: InputVar, moreInfo?: MoreInfo) => {
const newInputFields = produce(inputFieldsRef.current, (draft) => { const newInputFields = produce(inputFieldsRef.current, (draft) => {
const currentIndex = draft.findIndex(field => field.variable === data.variable) const currentIndex = draft.findIndex(field => field.variable === data.variable)
if (currentIndex === -1) { if (currentIndex === -1) {
@ -53,7 +83,10 @@ export const useFieldList = (
draft[currentIndex] = data draft[currentIndex] = data
}) })
handleInputFieldsChange(newInputFields) handleInputFieldsChange(newInputFields)
}, [handleInputFieldsChange]) // Update variable name in nodes if it has changed
if (moreInfo?.type === ChangeType.changeVarName)
handleOutVarRenameChange(nodeId, [nodeId, moreInfo.payload?.beforeKey || ''], [nodeId, moreInfo.payload?.afterKey || ''])
}, [handleInputFieldsChange, handleOutVarRenameChange, nodeId])
return { return {
inputFields, inputFields,
@ -65,5 +98,8 @@ export const useFieldList = (
showInputFieldEditor, showInputFieldEditor,
handleOpenInputFieldEditor, handleOpenInputFieldEditor,
handleCancelInputFieldEditor, handleCancelInputFieldEditor,
isShowRemoveVarConfirm,
hideRemoveVarConfirm,
onRemoveVarConfirm,
} }
} }

View File

@ -6,6 +6,7 @@ import type { InputVar } from '@/models/pipeline'
import ActionButton from '@/app/components/base/action-button' import ActionButton from '@/app/components/base/action-button'
import { useFieldList } from './hooks' import { useFieldList } from './hooks'
import FieldListContainer from './field-list-container' import FieldListContainer from './field-list-container'
import RemoveEffectVarConfirm from '@/app/components/workflow/nodes/_base/components/remove-effect-var-confirm'
type FieldListProps = { type FieldListProps = {
nodeId: string nodeId: string
@ -37,7 +38,10 @@ const FieldList = ({
handleOpenInputFieldEditor, handleOpenInputFieldEditor,
showInputFieldEditor, showInputFieldEditor,
editingField, editingField,
} = useFieldList(initialInputFields, onInputFieldsChange) isShowRemoveVarConfirm,
hideRemoveVarConfirm,
onRemoveVarConfirm,
} = useFieldList(initialInputFields, onInputFieldsChange, nodeId)
return ( return (
<div className='flex flex-col'> <div className='flex flex-col'>
@ -70,6 +74,11 @@ const FieldList = ({
onClose={handleCancelInputFieldEditor} onClose={handleCancelInputFieldEditor}
/> />
)} )}
<RemoveEffectVarConfirm
isShow={isShowRemoveVarConfirm}
onCancel={hideRemoveVarConfirm}
onConfirm={onRemoveVarConfirm}
/>
</div> </div>
) )
} }

View File

@ -37,7 +37,7 @@ const Panel: FC<NodePanelProps<DataSourceNodeType>> = ({ id, data }) => {
editingField, editingField,
handleSubmitField, handleSubmitField,
handleCancelInputFieldEditor, handleCancelInputFieldEditor,
} = useFieldList(variables, handleInputFieldVariablesChange) } = useFieldList(variables, handleInputFieldVariablesChange, id)
return ( return (
<div > <div >