mirror of https://github.com/langgenius/dify.git
feat: can remove
This commit is contained in:
parent
a18bcf3957
commit
89963ecf59
|
|
@ -266,6 +266,7 @@ const PromptEditor: FC<PromptEditorProps> = ({
|
|||
nodeTitle={hitlInputBlock.nodeTitle}
|
||||
formInputs={hitlInputBlock.formInputs}
|
||||
onFormInputsChange={hitlInputBlock.onFormInputsChange}
|
||||
onFormInputItemRemove={hitlInputBlock.onFormInputItemRemove}
|
||||
/>
|
||||
</>
|
||||
)
|
||||
|
|
|
|||
|
|
@ -19,6 +19,7 @@ type Props = {
|
|||
isSelected: boolean
|
||||
formInput?: FormInputItem
|
||||
onChange: (input: FormInputItem) => void
|
||||
onRemove: (varName: string) => void
|
||||
}
|
||||
|
||||
const ComponentUI: FC<Props> = ({
|
||||
|
|
@ -35,6 +36,7 @@ const ComponentUI: FC<Props> = ({
|
|||
},
|
||||
},
|
||||
onChange,
|
||||
onRemove,
|
||||
}) => {
|
||||
const { t } = useTranslation()
|
||||
const [isShowEditModal, {
|
||||
|
|
@ -42,6 +44,7 @@ const ComponentUI: FC<Props> = ({
|
|||
setFalse: hideEditModal,
|
||||
}] = useBoolean(false)
|
||||
|
||||
// Lexical delegate the click make it unable to add click by the method of react
|
||||
const editBtnRef = useRef<HTMLDivElement>(null)
|
||||
useEffect(() => {
|
||||
const editBtn = editBtnRef.current
|
||||
|
|
@ -54,6 +57,18 @@ const ComponentUI: FC<Props> = ({
|
|||
}
|
||||
}, [])
|
||||
|
||||
const removeBtnRef = useRef<HTMLDivElement>(null)
|
||||
useEffect(() => {
|
||||
const removeBtn = removeBtnRef.current
|
||||
if (removeBtn)
|
||||
removeBtn.addEventListener('click', () => onRemove(varName))
|
||||
|
||||
return () => {
|
||||
if (removeBtn)
|
||||
removeBtn.removeEventListener('click', () => onRemove(varName))
|
||||
}
|
||||
}, [onRemove, varName])
|
||||
|
||||
const handleChange = useCallback((newPayload: FormInputItem) => {
|
||||
onChange(newPayload)
|
||||
hideEditModal()
|
||||
|
|
@ -93,7 +108,7 @@ const ComponentUI: FC<Props> = ({
|
|||
</ActionButton>
|
||||
</div>
|
||||
|
||||
<div className='flex h-full items-center' >
|
||||
<div className='flex h-full items-center' ref={removeBtnRef}>
|
||||
<ActionButton size='s'>
|
||||
<RiDeleteBinLine className='size-4 text-text-tertiary' />
|
||||
</ActionButton>
|
||||
|
|
|
|||
|
|
@ -5,20 +5,22 @@ import ComponentUi from './component-ui'
|
|||
import type { FormInputItem } from '@/app/components/workflow/nodes/human-input/types'
|
||||
import produce from 'immer'
|
||||
|
||||
type QueryBlockComponentProps = {
|
||||
type Props = {
|
||||
nodeKey: string
|
||||
nodeTitle: string
|
||||
varName: string
|
||||
formInputs?: FormInputItem[]
|
||||
onChange: (inputs: FormInputItem[]) => void
|
||||
onRemove: (varName: string) => void
|
||||
}
|
||||
|
||||
const HITLInputComponent: FC<QueryBlockComponentProps> = ({
|
||||
const HITLInputComponent: FC<Props> = ({
|
||||
nodeKey,
|
||||
nodeTitle,
|
||||
varName,
|
||||
formInputs = [],
|
||||
onChange,
|
||||
onRemove,
|
||||
}) => {
|
||||
const [ref, isSelected] = useSelectOrDelete(nodeKey, DELETE_HITL_INPUT_BLOCK_COMMAND)
|
||||
const payload = formInputs.find(item => item.output_variable_name === varName)
|
||||
|
|
@ -46,6 +48,7 @@ const HITLInputComponent: FC<QueryBlockComponentProps> = ({
|
|||
isSelected={isSelected}
|
||||
formInput={payload}
|
||||
onChange={handleChange}
|
||||
onRemove={onRemove}
|
||||
/>
|
||||
</div>
|
||||
)
|
||||
|
|
|
|||
|
|
@ -23,6 +23,7 @@ const HITLInputReplacementBlock = ({
|
|||
nodeTitle,
|
||||
formInputs,
|
||||
onFormInputsChange,
|
||||
onFormInputItemRemove,
|
||||
}: HITLInputBlockType) => {
|
||||
const [editor] = useLexicalComposerContext()
|
||||
|
||||
|
|
@ -33,8 +34,14 @@ const HITLInputReplacementBlock = ({
|
|||
|
||||
const createHITLInputBlockNode = useCallback((textNode: TextNode): QueryBlockNode => {
|
||||
const varName = textNode.getTextContent().split('.')[1].replace(/#}}$/, '')
|
||||
return $applyNodeReplacement($createHITLInputNode(varName, nodeTitle, formInputs || [], onFormInputsChange!))
|
||||
}, [nodeTitle, formInputs, onFormInputsChange])
|
||||
return $applyNodeReplacement($createHITLInputNode(
|
||||
varName,
|
||||
nodeTitle,
|
||||
formInputs || [],
|
||||
onFormInputsChange!,
|
||||
onFormInputItemRemove!,
|
||||
))
|
||||
}, [nodeTitle, formInputs, onFormInputsChange, onFormInputItemRemove])
|
||||
|
||||
const getMatch = useCallback((text: string) => {
|
||||
const matchArr = REGEX.exec(text)
|
||||
|
|
|
|||
|
|
@ -8,6 +8,7 @@ export type SerializedNode = SerializedLexicalNode & {
|
|||
nodeTitle: string
|
||||
formInputs: FormInputItem[]
|
||||
onFormInputsChange: (inputs: FormInputItem[]) => void
|
||||
onFormInputItemRemove: (varName: string) => void
|
||||
}
|
||||
|
||||
export class HITLInputNode extends DecoratorNode<React.JSX.Element> {
|
||||
|
|
@ -15,6 +16,7 @@ export class HITLInputNode extends DecoratorNode<React.JSX.Element> {
|
|||
__nodeTitle: string
|
||||
__formInputs?: FormInputItem[]
|
||||
__onFormInputsChange: (inputs: FormInputItem[]) => void
|
||||
__onFormInputItemRemove: (varName: string) => void
|
||||
|
||||
isIsolated(): boolean {
|
||||
return true // This is necessary for drag-and-drop to work correctly
|
||||
|
|
@ -48,21 +50,34 @@ export class HITLInputNode extends DecoratorNode<React.JSX.Element> {
|
|||
return self.__onFormInputsChange
|
||||
}
|
||||
|
||||
getOnFormInputItemRemove(): (varName: string) => void {
|
||||
const self = this.getLatest()
|
||||
return self.__onFormInputItemRemove
|
||||
}
|
||||
|
||||
static clone(node: HITLInputNode): HITLInputNode {
|
||||
return new HITLInputNode(node.__variableName, node.__nodeTitle, node.__formInputs || [], node.__onFormInputsChange, node.__key)
|
||||
return new HITLInputNode(
|
||||
node.__variableName,
|
||||
node.__nodeTitle,
|
||||
node.__formInputs || [],
|
||||
node.__onFormInputsChange,
|
||||
node.__onFormInputItemRemove,
|
||||
node.__key,
|
||||
)
|
||||
}
|
||||
|
||||
isInline(): boolean {
|
||||
return true
|
||||
}
|
||||
|
||||
constructor(varName: string, nodeTitle: string, formInputs: FormInputItem[], onFormInputsChange: (inputs: FormInputItem[]) => void, key?: NodeKey) {
|
||||
constructor(varName: string, nodeTitle: string, formInputs: FormInputItem[], onFormInputsChange: (inputs: FormInputItem[]) => void, onFormInputItemRemove: (varName: string) => void, key?: NodeKey) {
|
||||
super(key)
|
||||
|
||||
this.__variableName = varName
|
||||
this.__nodeTitle = nodeTitle
|
||||
this.__formInputs = formInputs
|
||||
this.__onFormInputsChange = onFormInputsChange
|
||||
this.__onFormInputItemRemove = onFormInputItemRemove
|
||||
}
|
||||
|
||||
createDOM(): HTMLElement {
|
||||
|
|
@ -82,11 +97,18 @@ export class HITLInputNode extends DecoratorNode<React.JSX.Element> {
|
|||
nodeTitle={this.getNodeTitle()}
|
||||
formInputs={this.getFormInputs()}
|
||||
onChange={this.getOnFormInputsChange()}
|
||||
onRemove={this.getOnFormInputItemRemove()}
|
||||
/>
|
||||
}
|
||||
|
||||
static importJSON(serializedNode: SerializedNode): HITLInputNode {
|
||||
const node = $createHITLInputNode(serializedNode.variableName, serializedNode.nodeTitle, serializedNode.formInputs, serializedNode.onFormInputsChange)
|
||||
const node = $createHITLInputNode(
|
||||
serializedNode.variableName,
|
||||
serializedNode.nodeTitle,
|
||||
serializedNode.formInputs,
|
||||
serializedNode.onFormInputsChange,
|
||||
serializedNode.onFormInputItemRemove,
|
||||
)
|
||||
|
||||
return node
|
||||
}
|
||||
|
|
@ -99,6 +121,7 @@ export class HITLInputNode extends DecoratorNode<React.JSX.Element> {
|
|||
nodeTitle: this.getNodeTitle(),
|
||||
formInputs: this.getFormInputs(),
|
||||
onFormInputsChange: this.getOnFormInputsChange(),
|
||||
onFormInputItemRemove: this.getOnFormInputItemRemove(),
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -107,8 +130,14 @@ export class HITLInputNode extends DecoratorNode<React.JSX.Element> {
|
|||
}
|
||||
}
|
||||
|
||||
export function $createHITLInputNode(variableName: string, nodeTitle: string, formInputs: FormInputItem[], onFormInputsChange: (inputs: FormInputItem[]) => void): HITLInputNode {
|
||||
return new HITLInputNode(variableName, nodeTitle, formInputs, onFormInputsChange)
|
||||
export function $createHITLInputNode(variableName: string, nodeTitle: string, formInputs: FormInputItem[], onFormInputsChange: (inputs: FormInputItem[]) => void, onFormInputItemRemove: (varName: string) => void): HITLInputNode {
|
||||
return new HITLInputNode(
|
||||
variableName,
|
||||
nodeTitle,
|
||||
formInputs,
|
||||
onFormInputsChange,
|
||||
onFormInputItemRemove,
|
||||
)
|
||||
}
|
||||
|
||||
export function $isHITLInputNode(
|
||||
|
|
|
|||
|
|
@ -83,6 +83,7 @@ export type HITLInputBlockType = {
|
|||
nodeTitle: string
|
||||
formInputs?: FormInputItem[]
|
||||
onFormInputsChange?: (inputs: FormInputItem[]) => void
|
||||
onFormInputItemRemove: (varName: string) => void
|
||||
}
|
||||
|
||||
export type MenuTextMatch = {
|
||||
|
|
|
|||
|
|
@ -14,7 +14,9 @@ type Props = {
|
|||
onChange: (value: string) => void
|
||||
formInputs: FormInputItem[]
|
||||
onFormInputsChange: (payload: FormInputItem[]) => void
|
||||
onFormInputItemRemove: (varName: string) => void
|
||||
nodeTitle: string
|
||||
editorKey: number
|
||||
}
|
||||
|
||||
const FormContent: FC<Props> = ({
|
||||
|
|
@ -23,7 +25,9 @@ const FormContent: FC<Props> = ({
|
|||
onChange,
|
||||
formInputs,
|
||||
onFormInputsChange,
|
||||
onFormInputItemRemove,
|
||||
nodeTitle,
|
||||
editorKey,
|
||||
}) => {
|
||||
const { t } = useTranslation()
|
||||
const filterVar = () => true
|
||||
|
|
@ -40,6 +44,7 @@ const FormContent: FC<Props> = ({
|
|||
return (
|
||||
<div>
|
||||
<PromptEditor
|
||||
key={editorKey}
|
||||
value={value}
|
||||
onChange={onChange}
|
||||
className='min-h-[80px]'
|
||||
|
|
@ -48,6 +53,7 @@ const FormContent: FC<Props> = ({
|
|||
formInputs,
|
||||
nodeTitle,
|
||||
onFormInputsChange,
|
||||
onFormInputItemRemove,
|
||||
}}
|
||||
workflowVariableBlock={{
|
||||
show: true,
|
||||
|
|
|
|||
|
|
@ -36,6 +36,8 @@ const Panel: FC<NodePanelProps<HumanInputNodeType>> = ({
|
|||
handleTimeoutChange,
|
||||
handleFormContentChange,
|
||||
handleFormInputsChange,
|
||||
handleFormInputItemRemove,
|
||||
editorKey,
|
||||
} = useConfig(id, data)
|
||||
|
||||
const { availableVars, availableNodesWithParent } = useAvailableVarList(id, {
|
||||
|
|
@ -68,12 +70,14 @@ const Panel: FC<NodePanelProps<HumanInputNodeType>> = ({
|
|||
</div>
|
||||
</div>
|
||||
<FormContent
|
||||
editorKey={editorKey}
|
||||
nodeId={id}
|
||||
value={inputs.form_content}
|
||||
onChange={handleFormContentChange}
|
||||
nodeTitle={inputs.title}
|
||||
formInputs={inputs.inputs}
|
||||
onFormInputsChange={handleFormInputsChange}
|
||||
onFormInputItemRemove={handleFormInputItemRemove}
|
||||
/>
|
||||
</div>
|
||||
{/* user actions */}
|
||||
|
|
|
|||
|
|
@ -1,24 +1,44 @@
|
|||
import { useCallback, useEffect, useRef, useState } from 'react'
|
||||
import useNodeCrud from '../_base/hooks/use-node-crud'
|
||||
import type { FormInputItem, HumanInputNodeType } from './types'
|
||||
import produce from 'immer'
|
||||
|
||||
const useFormContent = (id: string, payload: HumanInputNodeType) => {
|
||||
const [editorKey, setEditorKey] = useState(0)
|
||||
const { inputs, setInputs } = useNodeCrud<HumanInputNodeType>(id, payload)
|
||||
const handleFormContentChange = (value: string) => {
|
||||
const inputsRef = useRef(inputs)
|
||||
useEffect(() => {
|
||||
inputsRef.current = inputs
|
||||
}, [inputs])
|
||||
const handleFormContentChange = useCallback((value: string) => {
|
||||
setInputs({
|
||||
...inputs,
|
||||
form_content: value,
|
||||
})
|
||||
}
|
||||
}, [inputs, setInputs])
|
||||
|
||||
const handleFormInputsChange = (formInputs: FormInputItem[]) => {
|
||||
const handleFormInputsChange = useCallback((formInputs: FormInputItem[]) => {
|
||||
setInputs({
|
||||
...inputs,
|
||||
inputs: formInputs,
|
||||
})
|
||||
}
|
||||
}, [inputs, setInputs])
|
||||
|
||||
const handleFormInputItemRemove = useCallback((varName: string) => {
|
||||
const inputs = inputsRef.current
|
||||
const newInputs = produce(inputs, (draft) => {
|
||||
draft.form_content = draft.form_content.replaceAll(`{{#$output.${varName}#}}`, '')
|
||||
draft.inputs = draft.inputs.filter(item => item.output_variable_name !== varName)
|
||||
})
|
||||
setInputs(newInputs)
|
||||
setEditorKey(editorKey + 1)
|
||||
}, [inputs, setInputs, editorKey])
|
||||
|
||||
return {
|
||||
editorKey,
|
||||
handleFormContentChange,
|
||||
handleFormInputsChange,
|
||||
handleFormInputItemRemove,
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,11 +0,0 @@
|
|||
'use client'
|
||||
|
||||
import InputField from '@/app/components/base/prompt-editor/plugins/hitl-input-block/input-field'
|
||||
|
||||
const Page = () => {
|
||||
return (
|
||||
<InputField />
|
||||
)
|
||||
}
|
||||
|
||||
export default Page
|
||||
Loading…
Reference in New Issue