handle var value change

This commit is contained in:
jZonG 2025-04-28 19:22:45 +08:00
parent 55a6ade90e
commit 85c98dd20a
6 changed files with 60 additions and 75 deletions

View File

@ -79,7 +79,6 @@ const useInspectVarsCrud = () => {
const editInspectVarValue = useCallback(async (nodeId: string, varId: string, value: any) => { const editInspectVarValue = useCallback(async (nodeId: string, varId: string, value: any) => {
await doEditInspectorVar({ await doEditInspectorVar({
nodeId,
varId, varId,
value, value,
}) })
@ -101,7 +100,6 @@ const useInspectVarsCrud = () => {
const renameInspectVarName = async (nodeId: string, varId: string, selector: ValueSelector) => { const renameInspectVarName = async (nodeId: string, varId: string, selector: ValueSelector) => {
await doEditInspectorVar({ await doEditInspectorVar({
nodeId,
varId, varId,
name: selector[1], name: selector[1],
}) })

View File

@ -49,4 +49,14 @@ export const systemVars: VarInInspect[] = [
value: 'Hello robot!', value: 'Hello robot!',
edited: false, edited: false,
}, },
{
id: 'sys2',
type: VarInInspectType.system,
name: 'user_id',
description: '',
selector: ['sys', 'user_id'],
value_type: VarType.string,
value: 'djflakjerlkjdlksfjslakjsdfl',
edited: false,
},
] ]

View File

@ -11,7 +11,6 @@ import Button from '@/app/components/base/button'
// import ActionButton from '@/app/components/base/action-button' // import ActionButton from '@/app/components/base/action-button'
// import Tooltip from '@/app/components/base/tooltip' // import Tooltip from '@/app/components/base/tooltip'
import BlockIcon from '@/app/components/workflow/block-icon' import BlockIcon from '@/app/components/workflow/block-icon'
import { BubbleX } from '@/app/components/base/icons/src/vender/line/others'
import { Variable02 } from '@/app/components/base/icons/src/vender/solid/development' import { Variable02 } from '@/app/components/base/icons/src/vender/solid/development'
import Group from './group' import Group from './group'
import useCurrentVars from '../hooks/use-inspect-vars-crud' import useCurrentVars from '../hooks/use-inspect-vars-crud'
@ -39,6 +38,8 @@ const Left = ({
deleteAllInspectorVars, deleteAllInspectorVars,
} = useCurrentVars() } = useCurrentVars()
const showDivider = environmentVariables.length > 0 || conversationVars.length > 0 || systemVars.length > 0
// TODO node selection // TODO node selection
const selectedNode = 3 < 4 const selectedNode = 3 < 4
@ -69,34 +70,21 @@ const Left = ({
handleSelect={handleVarSelect} handleSelect={handleVarSelect}
/> />
)} )}
{/* group CHAT VAR */} {/* group SYSTEM VAR */}
<div className='p-0.5'> {conversationVars.length > 0 && (
{/* node item */} <Group
<div className='flex h-6 items-center gap-0.5'> varType={VarInInspectType.system}
<RiArrowRightSLine className='h-3 w-3 rotate-90 text-text-tertiary' /> varList={systemVars}
<div className='flex grow cursor-pointer items-center gap-1'> currentVar={currentNodeVar}
<div className='system-xs-medium-uppercase truncate text-text-tertiary'>{t('workflow.chatVariable.panelTitle')}</div> handleSelect={handleVarSelect}
</div> />
</div> )}
{/* var item list */}
<div className='px-0.5'>
<div className={cn('relative flex cursor-pointer items-center gap-1 rounded-md px-3 py-1 hover:bg-state-base-hover')}>
<BubbleX className='h-4 w-4 shrink-0 text-util-colors-teal-teal-700' />
<div className='system-sm-medium grow truncate text-text-secondary'>chat_history</div>
<div className='system-xs-regular shrink-0 text-text-tertiary'>array</div>
</div>
<div className={cn('relative flex cursor-pointer items-center gap-1 rounded-md px-3 py-1 hover:bg-state-base-hover')}>
{selectedNode && <span className='absolute left-1.5 top-[10.5px] h-[3px] w-[3px] rounded-full bg-text-accent-secondary'></span>}
<BubbleX className='h-4 w-4 shrink-0 text-util-colors-teal-teal-700' />
<div className='system-sm-medium grow truncate text-text-secondary'>custom_chat_history</div>
<div className='system-xs-regular shrink-0 text-text-tertiary'>array</div>
</div>
</div>
</div>
{/* divider */} {/* divider */}
<div className='px-4 py-1'> {showDivider && (
<div className='h-px bg-divider-subtle'></div> <div className='px-4 py-1'>
</div> <div className='h-px bg-divider-subtle'></div>
</div>
)}
{/* group nodes */} {/* group nodes */}
<div className='p-0.5'> <div className='p-0.5'>
{/* node item */} {/* node item */}

View File

@ -36,8 +36,14 @@ const Right = ({
const { const {
resetToLastRunVar, resetToLastRunVar,
editInspectVarValue,
} = useCurrentVars() } = useCurrentVars()
const handleValueChange = (varId: string, value: any) => {
if (!currentNodeVar) return
editInspectVarValue(currentNodeVar.nodeId, varId, value)
}
const resetValue = () => { const resetValue = () => {
if (!currentNodeVar) return if (!currentNodeVar) return
resetToLastRunVar(currentNodeVar.nodeId, currentNodeVar.var.name) resetToLastRunVar(currentNodeVar.nodeId, currentNodeVar.var.name)
@ -109,7 +115,7 @@ const Right = ({
{/* content */} {/* content */}
<div className='grow p-2'> <div className='grow p-2'>
{!currentNodeVar && <Empty />} {!currentNodeVar && <Empty />}
{currentNodeVar && <ValueContent currentVar={currentNodeVar.var} />} {currentNodeVar && <ValueContent currentVar={currentNodeVar.var} handleValueChange={handleValueChange} />}
</div> </div>
</div> </div>
) )

View File

@ -1,6 +1,5 @@
import { useEffect, useRef, useState } from 'react' import { useEffect, useRef, useState } from 'react'
// import { useTranslation } from 'react-i18next' import { useDebounceFn } from 'ahooks'
import { debounce } from 'lodash-es'
import Textarea from '@/app/components/base/textarea' import Textarea from '@/app/components/base/textarea'
import SchemaEditor from '@/app/components/workflow/nodes/llm/components/json-schema-config-modal/schema-editor' import SchemaEditor from '@/app/components/workflow/nodes/llm/components/json-schema-config-modal/schema-editor'
import { FileUploaderInAttachmentWrapper } from '@/app/components/base/file-uploader' import { FileUploaderInAttachmentWrapper } from '@/app/components/base/file-uploader'
@ -23,38 +22,14 @@ import type { VarInInspect } from '@/types/workflow'
import { VarInInspectType } from '@/types/workflow' import { VarInInspectType } from '@/types/workflow'
import cn from '@/utils/classnames' import cn from '@/utils/classnames'
export const MOCK_DATA = {
id: 'var-jfkldjjfkldaf-dfhekdfj',
type: 'node',
// type: 'conversation',
// type: 'environment',
name: 'out_put',
// value_type: 'string',
// value_type: 'number',
// value_type: 'object',
// value_type: 'array[string]',
// value_type: 'array[number]',
// value_type: 'array[object]',
// value_type: 'file',
value_type: 'array[file]',
// value: 'tuituitui',
// value: ['aaa', 'bbb', 'ccc'],
// value: {
// abc: '123',
// def: 456,
// fff: true,
// },
value: [],
edited: true,
}
type Props = { type Props = {
currentVar: VarInInspect currentVar: VarInInspect
handleValueChange: (varId: string, value: any) => void
} }
const ValueContent = ({ const ValueContent = ({
// currentVar = MOCK_DATA as any, // TODO remove this line
currentVar, currentVar,
handleValueChange,
}: Props) => { }: Props) => {
const contentContainerRef = useRef<HTMLDivElement>(null) const contentContainerRef = useRef<HTMLDivElement>(null)
const errorMessageRef = useRef<HTMLDivElement>(null) const errorMessageRef = useRef<HTMLDivElement>(null)
@ -62,6 +37,7 @@ const ValueContent = ({
const showTextEditor = currentVar.value_type === 'secret' || currentVar.value_type === 'string' || currentVar.value_type === 'number' const showTextEditor = currentVar.value_type === 'secret' || currentVar.value_type === 'string' || currentVar.value_type === 'number'
const showJSONEditor = currentVar.value_type === 'object' || currentVar.value_type === 'array[string]' || currentVar.value_type === 'array[number]' || currentVar.value_type === 'array[object]' const showJSONEditor = currentVar.value_type === 'object' || currentVar.value_type === 'array[string]' || currentVar.value_type === 'array[number]' || currentVar.value_type === 'array[object]'
const showFileEditor = currentVar.value_type === 'file' || currentVar.value_type === 'array[file]' const showFileEditor = currentVar.value_type === 'file' || currentVar.value_type === 'array[file]'
const textEditorDisabled = currentVar.type === VarInInspectType.environment || (currentVar.type === VarInInspectType.system && currentVar.name !== 'query')
const [value, setValue] = useState<any>() const [value, setValue] = useState<any>()
const [jsonSchema, setJsonSchema] = useState() const [jsonSchema, setJsonSchema] = useState()
@ -77,8 +53,11 @@ const ValueContent = ({
: [], : [],
) )
const { run: debounceValueChange } = useDebounceFn(handleValueChange, { wait: 500 })
// update default value when id changed // update default value when id changed
useEffect(() => { useEffect(() => {
console.log('currentVar', currentVar)
if (showTextEditor) { if (showTextEditor) {
if (!currentVar.value) if (!currentVar.value)
return setValue('') return setValue('')
@ -107,7 +86,7 @@ const ValueContent = ({
if (/^-?\d+(\.)?(\d+)?$/.test(value)) if (/^-?\d+(\.)?(\d+)?$/.test(value))
setValue(value) setValue(value)
} }
// TODO call api of value update debounceValueChange(currentVar.id, value)
} }
const jsonValueValidate = (value: string, type: string) => { const jsonValueValidate = (value: string, type: string) => {
@ -152,21 +131,26 @@ const ValueContent = ({
if (jsonValueValidate(value, currentVar.value_type)) { if (jsonValueValidate(value, currentVar.value_type)) {
const parsed = JSON.parse(value) const parsed = JSON.parse(value)
setJsonSchema(parsed) setJsonSchema(parsed)
// TODO call api of value update debounceValueChange(currentVar.id, parsed)
} }
} }
const handleFileChange = (value: any) => { const fileValueValidate = (fileList: any[]) => {
console.log('value', value) if (fileList.every(file => file.upload_file_id))
return true
return false
}
const handleFileChange = (value: any[]) => {
setFileValue(value) setFileValue(value)
// TODO check every file upload progress // check every file upload progress
// invoke update api after every file uploaded // invoke update api after every file uploaded
if (currentVar.value_type === 'file') { if (!fileValueValidate(value))
// TODO call api of value update return
} if (currentVar.value_type === 'file')
if (currentVar.value_type === 'array[file]') { debounceValueChange(currentVar.id, value[0])
// TODO call api of value update if (currentVar.value_type === 'array[file]')
} debounceValueChange(currentVar.id, value)
} }
// get editor height // get editor height
@ -194,8 +178,8 @@ const ValueContent = ({
<div className={cn('grow')} style={{ height: `${editorHeight}px` }}> <div className={cn('grow')} style={{ height: `${editorHeight}px` }}>
{showTextEditor && ( {showTextEditor && (
<Textarea <Textarea
readOnly={currentVar.type === VarInInspectType.environment} readOnly={textEditorDisabled}
disabled={currentVar.type === VarInInspectType.environment} disabled={textEditorDisabled}
className='h-full' className='h-full'
value={value as any} value={value as any}
onChange={e => handleTextChange(e.target.value)} onChange={e => handleTextChange(e.target.value)}
@ -206,7 +190,7 @@ const ValueContent = ({
className='overflow-y-auto' className='overflow-y-auto'
hideTopMenu hideTopMenu
schema={json} schema={json}
onUpdate={debounce(handleEditorChange)} onUpdate={handleEditorChange}
/> />
)} )}
{showFileEditor && ( {showFileEditor && (

View File

@ -169,7 +169,7 @@ export const useSysVarValues = (appId: string) => {
return Promise.resolve(systemVars.map((item) => { return Promise.resolve(systemVars.map((item) => {
return { return {
...item, ...item,
value: `${item.value}${index++}`, value: item.value_type === 'string' ? `${item.value}${index++}` : item.value,
} }
})) }))
}, },
@ -212,7 +212,6 @@ export const useEditInspectorVar = (appId: string) => {
return useMutation({ return useMutation({
mutationKey: [NAME_SPACE, 'edit inspector var', appId], mutationKey: [NAME_SPACE, 'edit inspector var', appId],
mutationFn: async (params: { mutationFn: async (params: {
nodeId: string
varId: string varId: string
name?: string name?: string
value?: any value?: any