mirror of
https://git.mirrors.martin98.com/https://github.com/langgenius/dify.git
synced 2025-08-19 16:19:12 +08:00
feat: handle value picker in body file selector
This commit is contained in:
parent
dca4f9fe9c
commit
8efc63a705
@ -8,6 +8,7 @@ import {
|
|||||||
} from '@remixicon/react'
|
} from '@remixicon/react'
|
||||||
import produce from 'immer'
|
import produce from 'immer'
|
||||||
import { useStoreApi } from 'reactflow'
|
import { useStoreApi } from 'reactflow'
|
||||||
|
import RemoveButton from '../remove-button'
|
||||||
import VarReferencePopup from './var-reference-popup'
|
import VarReferencePopup from './var-reference-popup'
|
||||||
import { getNodeInfoById, isConversationVar, isENV, isSystemVar } from './utils'
|
import { getNodeInfoById, isConversationVar, isENV, isSystemVar } from './utils'
|
||||||
import ConstantField from './constant-field'
|
import ConstantField from './constant-field'
|
||||||
@ -52,6 +53,8 @@ type Props = {
|
|||||||
isAddBtnTrigger?: boolean
|
isAddBtnTrigger?: boolean
|
||||||
schema?: Partial<CredentialFormSchema>
|
schema?: Partial<CredentialFormSchema>
|
||||||
valueTypePlaceHolder?: string
|
valueTypePlaceHolder?: string
|
||||||
|
isInTable?: boolean
|
||||||
|
onRemove?: () => void
|
||||||
}
|
}
|
||||||
|
|
||||||
const VarReferencePicker: FC<Props> = ({
|
const VarReferencePicker: FC<Props> = ({
|
||||||
@ -71,6 +74,8 @@ const VarReferencePicker: FC<Props> = ({
|
|||||||
isAddBtnTrigger,
|
isAddBtnTrigger,
|
||||||
schema,
|
schema,
|
||||||
valueTypePlaceHolder,
|
valueTypePlaceHolder,
|
||||||
|
isInTable,
|
||||||
|
onRemove,
|
||||||
}) => {
|
}) => {
|
||||||
const { t } = useTranslation()
|
const { t } = useTranslation()
|
||||||
const store = useStoreApi()
|
const store = useStoreApi()
|
||||||
@ -243,109 +248,117 @@ const VarReferencePicker: FC<Props> = ({
|
|||||||
if (readonly)
|
if (readonly)
|
||||||
return
|
return
|
||||||
!isConstant ? setOpen(!open) : setControlFocus(Date.now())
|
!isConstant ? setOpen(!open) : setControlFocus(Date.now())
|
||||||
}} className='!flex'>
|
}} className='!flex group/picker-trigger-wrap relative'>
|
||||||
{isAddBtnTrigger
|
<>
|
||||||
? (
|
{isAddBtnTrigger
|
||||||
<div>
|
? (
|
||||||
<AddButton onClick={() => { }}></AddButton>
|
<div>
|
||||||
</div>
|
<AddButton onClick={() => { }}></AddButton>
|
||||||
)
|
|
||||||
: (<div ref={!isSupportConstantValue ? triggerRef : null} className={cn((open || isFocus) ? 'border-gray-300' : 'border-gray-100', 'relative group/wrap flex items-center w-full h-8', !isSupportConstantValue && 'p-1 rounded-lg bg-gray-100 border')}>
|
|
||||||
{isSupportConstantValue
|
|
||||||
? <div onClick={(e) => {
|
|
||||||
e.stopPropagation()
|
|
||||||
setOpen(false)
|
|
||||||
setControlFocus(Date.now())
|
|
||||||
}} className='h-full mr-1 flex items-center space-x-1'>
|
|
||||||
<TypeSelector
|
|
||||||
noLeft
|
|
||||||
trigger={
|
|
||||||
<div className='flex items-center h-8 px-2 radius-md bg-components-input-bg-normal'>
|
|
||||||
<div className='mr-1 system-sm-regular text-components-input-text-filled'>{varKindTypes.find(item => item.value === varKindType)?.label}</div>
|
|
||||||
<RiArrowDownSLine className='w-4 h-4 text-text-quaternary' />
|
|
||||||
</div>
|
|
||||||
}
|
|
||||||
popupClassName='top-8'
|
|
||||||
readonly={readonly}
|
|
||||||
value={varKindType}
|
|
||||||
options={varKindTypes}
|
|
||||||
onChange={handleVarKindTypeChange}
|
|
||||||
showChecked
|
|
||||||
/>
|
|
||||||
</div>
|
</div>
|
||||||
: (!hasValue && <div className='ml-1.5 mr-1'>
|
)
|
||||||
<Variable02 className='w-3.5 h-3.5 text-gray-400' />
|
: (<div ref={!isSupportConstantValue ? triggerRef : null} className={cn((open || isFocus) ? 'border-gray-300' : 'border-gray-100', 'relative group/wrap flex items-center w-full h-8', !isSupportConstantValue && 'p-1 rounded-lg bg-gray-100 border', isInTable && 'bg-transparent border-none')}>
|
||||||
</div>)}
|
{isSupportConstantValue
|
||||||
{isConstant
|
? <div onClick={(e) => {
|
||||||
? (
|
e.stopPropagation()
|
||||||
<ConstantField
|
setOpen(false)
|
||||||
value={value as string}
|
setControlFocus(Date.now())
|
||||||
onChange={onChange as ((value: string | number, varKindType: VarKindType, varInfo?: Var) => void)}
|
}} className='h-full mr-1 flex items-center space-x-1'>
|
||||||
schema={schema as CredentialFormSchema}
|
<TypeSelector
|
||||||
readonly={readonly}
|
noLeft
|
||||||
/>
|
trigger={
|
||||||
)
|
<div className='flex items-center h-8 px-2 radius-md bg-components-input-bg-normal'>
|
||||||
: (
|
<div className='mr-1 system-sm-regular text-components-input-text-filled'>{varKindTypes.find(item => item.value === varKindType)?.label}</div>
|
||||||
<VarPickerWrap
|
<RiArrowDownSLine className='w-4 h-4 text-text-quaternary' />
|
||||||
onClick={() => {
|
</div>
|
||||||
if (readonly)
|
}
|
||||||
return
|
popupClassName='top-8'
|
||||||
!isConstant ? setOpen(!open) : setControlFocus(Date.now())
|
readonly={readonly}
|
||||||
}}
|
value={varKindType}
|
||||||
className='grow h-full'
|
options={varKindTypes}
|
||||||
>
|
onChange={handleVarKindTypeChange}
|
||||||
<div ref={isSupportConstantValue ? triggerRef : null} className={cn('h-full', isSupportConstantValue && 'flex items-center pl-1 py-1 rounded-lg bg-gray-100')}>
|
showChecked
|
||||||
<div className={cn('h-full items-center px-1.5 rounded-[5px]', hasValue ? 'bg-white inline-flex' : 'flex')}>
|
/>
|
||||||
{hasValue
|
</div>
|
||||||
? (
|
: (!hasValue && <div className='ml-1.5 mr-1'>
|
||||||
<>
|
<Variable02 className='w-3.5 h-3.5 text-gray-400' />
|
||||||
{isShowNodeName && !isEnv && !isChatVar && (
|
</div>)}
|
||||||
<div className='flex items-center'>
|
{isConstant
|
||||||
<div className='p-[1px]'>
|
? (
|
||||||
<VarBlockIcon
|
<ConstantField
|
||||||
className='!text-gray-900'
|
value={value as string}
|
||||||
type={outputVarNode?.type || BlockEnum.Start}
|
onChange={onChange as ((value: string | number, varKindType: VarKindType, varInfo?: Var) => void)}
|
||||||
/>
|
schema={schema as CredentialFormSchema}
|
||||||
|
readonly={readonly}
|
||||||
|
/>
|
||||||
|
)
|
||||||
|
: (
|
||||||
|
<VarPickerWrap
|
||||||
|
onClick={() => {
|
||||||
|
if (readonly)
|
||||||
|
return
|
||||||
|
!isConstant ? setOpen(!open) : setControlFocus(Date.now())
|
||||||
|
}}
|
||||||
|
className='grow h-full'
|
||||||
|
>
|
||||||
|
<div ref={isSupportConstantValue ? triggerRef : null} className={cn('h-full', isSupportConstantValue && 'flex items-center pl-1 py-1 rounded-lg bg-gray-100')}>
|
||||||
|
<div className={cn('h-full items-center px-1.5 rounded-[5px]', hasValue ? 'bg-white inline-flex' : 'flex')}>
|
||||||
|
{hasValue
|
||||||
|
? (
|
||||||
|
<>
|
||||||
|
{isShowNodeName && !isEnv && !isChatVar && (
|
||||||
|
<div className='flex items-center'>
|
||||||
|
<div className='p-[1px]'>
|
||||||
|
<VarBlockIcon
|
||||||
|
className='!text-gray-900'
|
||||||
|
type={outputVarNode?.type || BlockEnum.Start}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div className='mx-0.5 text-xs font-medium text-gray-700 truncate' title={outputVarNode?.title} style={{
|
||||||
|
maxWidth: maxNodeNameWidth,
|
||||||
|
}}>{outputVarNode?.title}</div>
|
||||||
|
<Line3 className='mr-0.5'></Line3>
|
||||||
</div>
|
</div>
|
||||||
<div className='mx-0.5 text-xs font-medium text-gray-700 truncate' title={outputVarNode?.title} style={{
|
)}
|
||||||
maxWidth: maxNodeNameWidth,
|
<div className='flex items-center text-primary-600'>
|
||||||
}}>{outputVarNode?.title}</div>
|
{!hasValue && <Variable02 className='w-3.5 h-3.5' />}
|
||||||
<Line3 className='mr-0.5'></Line3>
|
{isEnv && <Env className='w-3.5 h-3.5 text-util-colors-violet-violet-600' />}
|
||||||
|
{isChatVar && <BubbleX className='w-3.5 h-3.5 text-util-colors-teal-teal-700' />}
|
||||||
|
<div className={cn('ml-0.5 text-xs font-medium truncate', (isEnv || isChatVar) && '!text-text-secondary')} title={varName} style={{
|
||||||
|
maxWidth: maxVarNameWidth,
|
||||||
|
}}>{varName}</div>
|
||||||
</div>
|
</div>
|
||||||
)}
|
<div className='ml-0.5 text-xs font-normal text-gray-500 capitalize truncate' title={type} style={{
|
||||||
<div className='flex items-center text-primary-600'>
|
maxWidth: maxTypeWidth,
|
||||||
{!hasValue && <Variable02 className='w-3.5 h-3.5' />}
|
}}>{type}</div>
|
||||||
{isEnv && <Env className='w-3.5 h-3.5 text-util-colors-violet-violet-600' />}
|
</>
|
||||||
{isChatVar && <BubbleX className='w-3.5 h-3.5 text-util-colors-teal-teal-700' />}
|
)
|
||||||
<div className={cn('ml-0.5 text-xs font-medium truncate', (isEnv || isChatVar) && '!text-text-secondary')} title={varName} style={{
|
: <div className='text-[13px] font-normal text-gray-400'>{t('workflow.common.setVarValuePlaceholder')}</div>}
|
||||||
maxWidth: maxVarNameWidth,
|
</div>
|
||||||
}}>{varName}</div>
|
|
||||||
</div>
|
|
||||||
<div className='ml-0.5 text-xs font-normal text-gray-500 capitalize truncate' title={type} style={{
|
|
||||||
maxWidth: maxTypeWidth,
|
|
||||||
}}>{type}</div>
|
|
||||||
</>
|
|
||||||
)
|
|
||||||
: <div className='text-[13px] font-normal text-gray-400'>{t('workflow.common.setVarValuePlaceholder')}</div>}
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
|
||||||
|
|
||||||
</VarPickerWrap>
|
</VarPickerWrap>
|
||||||
|
)}
|
||||||
|
{(hasValue && !readonly && !isInTable) && (<div
|
||||||
|
className='invisible group-hover/wrap:visible absolute h-5 right-1 top-[50%] translate-y-[-50%] group p-1 rounded-md hover:bg-black/5 cursor-pointer'
|
||||||
|
onClick={handleClearVar}
|
||||||
|
>
|
||||||
|
<RiCloseLine className='w-3.5 h-3.5 text-gray-500 group-hover:text-gray-800' />
|
||||||
|
</div>)}
|
||||||
|
{!hasValue && valueTypePlaceHolder && (
|
||||||
|
<Badge
|
||||||
|
className=' absolute right-1 top-[50%] translate-y-[-50%] capitalize'
|
||||||
|
text={valueTypePlaceHolder}
|
||||||
|
uppercase={false}
|
||||||
|
/>
|
||||||
)}
|
)}
|
||||||
{(hasValue && !readonly) && (<div
|
|
||||||
className='invisible group-hover/wrap:visible absolute h-5 right-1 top-[50%] translate-y-[-50%] group p-1 rounded-md hover:bg-black/5 cursor-pointer'
|
|
||||||
onClick={handleClearVar}
|
|
||||||
>
|
|
||||||
<RiCloseLine className='w-3.5 h-3.5 text-gray-500 group-hover:text-gray-800' />
|
|
||||||
</div>)}
|
</div>)}
|
||||||
{!hasValue && valueTypePlaceHolder && (
|
{!readonly && isInTable && (
|
||||||
<Badge
|
<RemoveButton
|
||||||
className=' absolute right-1 top-[50%] translate-y-[-50%] capitalize'
|
className='group-hover/picker-trigger-wrap:block hidden absolute right-1 top-0.5'
|
||||||
text={valueTypePlaceHolder}
|
onClick={() => onRemove?.()}
|
||||||
uppercase={false}
|
/>
|
||||||
/>
|
)}
|
||||||
)}
|
</>
|
||||||
</div>)}
|
|
||||||
</WrapElem>
|
</WrapElem>
|
||||||
<PortalToFollowElemContent style={{
|
<PortalToFollowElemContent style={{
|
||||||
zIndex: 100,
|
zIndex: 100,
|
||||||
|
@ -54,7 +54,7 @@ const KeyValueItem: FC<Props> = ({
|
|||||||
})
|
})
|
||||||
onChange(newPayload)
|
onChange(newPayload)
|
||||||
}
|
}
|
||||||
}, [onChange, onAdd, isLastItem, payload])
|
}, [onChange, payload])
|
||||||
|
|
||||||
const filterOnlyFileVariable = (varPayload: Var) => {
|
const filterOnlyFileVariable = (varPayload: Var) => {
|
||||||
return [VarType.file, VarType.arrayFile].includes(varPayload.type)
|
return [VarType.file, VarType.arrayFile].includes(varPayload.type)
|
||||||
@ -109,6 +109,8 @@ const KeyValueItem: FC<Props> = ({
|
|||||||
value={payload.file || []}
|
value={payload.file || []}
|
||||||
onChange={handleChange('file')}
|
onChange={handleChange('file')}
|
||||||
filterVar={filterOnlyFileVariable}
|
filterVar={filterOnlyFileVariable}
|
||||||
|
isInTable
|
||||||
|
onRemove={onRemove}
|
||||||
/>
|
/>
|
||||||
)
|
)
|
||||||
: (
|
: (
|
||||||
|
Loading…
x
Reference in New Issue
Block a user