feat: handle value picker in body file selector

This commit is contained in:
Joel 2024-08-29 16:36:18 +08:00
parent dca4f9fe9c
commit 8efc63a705
2 changed files with 112 additions and 97 deletions

View File

@ -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,

View File

@ -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}
/> />
) )
: ( : (