feat: in placeholder choose var

This commit is contained in:
Joel 2025-08-25 16:29:29 +08:00
parent e5a2172a85
commit fda19d3f0e
3 changed files with 171 additions and 151 deletions

View File

@ -37,6 +37,10 @@ const InputField: React.FC<Props> = ({
if (!draft.placeholder)
draft.placeholder = { type: 'const', selector: [], value: '' }
draft.placeholder[key] = value
if(key === 'selector')
draft.placeholder.type = 'variable'
else if(key === 'value')
draft.placeholder.type = 'const'
})
setTempPayload(nextValue)
}

View File

@ -22,9 +22,11 @@ type Props = {
const i18nPrefix = 'workflow.nodes.humanInput.insertInputField'
type PlaceholderProps = {
varPickerProps: any
onTypeClick: (isVariable: boolean) => void
}
const Placeholder = ({
varPickerProps,
onTypeClick,
}: PlaceholderProps) => {
const { t } = useTranslation()
@ -35,7 +37,12 @@ const Placeholder = ({
i18nKey={`${i18nPrefix}.prePopulateFieldPlaceholder`}
components={{
staticContent: <TagLabel type='edit' className='mx-1' onClick={() => onTypeClick(false)}>{t(`${i18nPrefix}.staticContent`)}</TagLabel>,
variable: <TagLabel type='variable' className='mx-1' onClick={() => onTypeClick(true)}>{t(`${i18nPrefix}.variable`)}</TagLabel>,
variable: <VarReferencePicker
{...varPickerProps}
trigger={
<TagLabel type='variable' className='mx-1'>{t(`${i18nPrefix}.variable`)}</TagLabel>
}
/>,
}}
/>
</div>
@ -60,19 +67,23 @@ const PrePopulate: FC<Props> = ({
const [isFocus, setIsFocus] = useState(false)
const varPickerProps = {
nodeId,
value: valueSelector || [],
onChange: onValueSelectorChange!,
readonly: false,
zIndex: 1000,
}
const isShowPlaceholder = !onPlaceholderClicked && (isVariable ? (!valueSelector || valueSelector.length === 0) : !value)
if (isShowPlaceholder)
return <Placeholder onTypeClick={handleTypeChange} />
return <Placeholder varPickerProps={varPickerProps} onTypeClick={handleTypeChange} />
if (isVariable) {
return (
<div>
<VarReferencePicker
nodeId={nodeId}
value={valueSelector || []}
onChange={onValueSelectorChange!}
readonly={false}
zIndex={1000}
{...varPickerProps}
/>
<TypeSwitch isVariable={isVariable} onIsVariableChange={handleTypeChange} />
</div>

View File

@ -61,6 +61,7 @@ type Props = {
filterVar?: (payload: Var, valueSelector: ValueSelector) => boolean
availableNodes?: Node[]
availableVars?: NodeOutPutVar[]
trigger?: React.ReactNode
isAddBtnTrigger?: boolean
schema?: Partial<CredentialFormSchema>
valueTypePlaceHolder?: string
@ -92,6 +93,7 @@ const VarReferencePicker: FC<Props> = ({
filterVar = () => true,
availableNodes: passedInAvailableNodes,
availableVars: passedInAvailableVars,
trigger,
isAddBtnTrigger,
schema,
valueTypePlaceHolder,
@ -392,156 +394,159 @@ const VarReferencePicker: FC<Props> = ({
onOpenChange={setOpen}
placement={isAddBtnTrigger ? 'bottom-end' : 'bottom-start'}
>
<WrapElem onClick={() => {
if (readonly)
return
!isConstant ? setOpen(!open) : setControlFocus(Date.now())
}} className='group/picker-trigger-wrap relative !flex'>
<>
{isAddBtnTrigger
? (
<div>
<AddButton onClick={noop}></AddButton>
</div>
)
: (<div ref={!isSupportConstantValue ? triggerRef : null} className={cn((open || isFocus) ? 'border-gray-300' : 'border-gray-100', 'group/wrap relative flex h-8 w-full items-center', !isSupportConstantValue && 'rounded-lg bg-components-input-bg-normal p-1', isInTable && 'border-none bg-transparent', readonly && 'bg-components-input-bg-disabled')}>
{isSupportConstantValue
? <div onClick={(e) => {
e.stopPropagation()
setOpen(false)
setControlFocus(Date.now())
}} className='mr-1 flex h-full items-center space-x-1'>
<TypeSelector
noLeft
trigger={
<div className='radius-md flex h-8 items-center bg-components-input-bg-normal px-2'>
<div className='system-sm-regular mr-1 text-components-input-text-filled'>{varKindTypes.find(item => item.value === varKindType)?.label}</div>
<RiArrowDownSLine className='h-4 w-4 text-text-quaternary' />
</div>
}
popupClassName='top-8'
readonly={readonly}
value={varKindType}
options={varKindTypes}
onChange={handleVarKindTypeChange}
showChecked
/>
{trigger && <PortalToFollowElemTrigger onClick={() => setOpen(!open)}>{trigger}</PortalToFollowElemTrigger>}
{!trigger && (
<WrapElem onClick={() => {
if (readonly)
return
!isConstant ? setOpen(!open) : setControlFocus(Date.now())
}} className='group/picker-trigger-wrap relative !flex'>
<>
{isAddBtnTrigger
? (
<div>
<AddButton onClick={noop}></AddButton>
</div>
: (!hasValue && <div className='ml-1.5 mr-1'>
<Variable02 className={`h-4 w-4 ${readonly ? 'text-components-input-text-disabled' : 'text-components-input-text-placeholder'}`} />
</div>)}
{isConstant
? (
<ConstantField
value={value as string}
onChange={onChange as ((value: string | number, varKindType: VarKindType, varInfo?: Var) => void)}
schema={schemaWithDynamicSelect as CredentialFormSchema}
readonly={readonly}
isLoading={isLoading}
/>
)
: (
<VarPickerWrap
onClick={() => {
if (readonly)
return
!isConstant ? setOpen(!open) : setControlFocus(Date.now())
}}
className='h-full grow'
>
<div ref={isSupportConstantValue ? triggerRef : null} className={cn('h-full', isSupportConstantValue && 'flex items-center rounded-lg bg-components-panel-bg py-1 pl-1')}>
<Tooltip noDecoration={isShowAPart} popupContent={tooltipPopup}>
<div className={cn('h-full items-center rounded-[5px] px-1.5', hasValue ? 'inline-flex bg-components-badge-white-to-dark' : 'flex')}>
{hasValue
? (
<>
{isShowNodeName && !isEnv && !isChatVar && (
<div className='flex items-center' onClick={(e) => {
if (e.metaKey || e.ctrlKey) {
e.stopPropagation()
handleVariableJump(outputVarNode?.id)
}
}}>
<div className='h-3 px-[1px]'>
{outputVarNode?.type && <VarBlockIcon
className='!text-text-primary'
type={outputVarNode.type}
/>}
</div>
<div className='mx-0.5 truncate text-xs font-medium text-text-secondary' title={outputVarNode?.title} style={{
maxWidth: maxNodeNameWidth,
}}>{outputVarNode?.title}</div>
<Line3 className='mr-0.5'></Line3>
</div>
)}
{isShowAPart && (
<div className='flex items-center'>
<RiMoreLine className='h-3 w-3 text-text-secondary' />
<Line3 className='mr-0.5 text-divider-deep'></Line3>
</div>
)}
<div className='flex items-center text-text-accent'>
{isLoading && <RiLoader4Line className='h-3.5 w-3.5 animate-spin text-text-secondary' />}
<VariableIconWithColor
variableCategory={variableCategory}
isExceptionVariable={isException}
/>
<div className={cn('ml-0.5 truncate text-xs font-medium', isEnv && '!text-text-secondary', isChatVar && 'text-util-colors-teal-teal-700', isException && 'text-text-warning')} title={varName} style={{
maxWidth: maxVarNameWidth,
}}>{varName}</div>
</div>
<div className='system-xs-regular ml-0.5 truncate text-center capitalize text-text-tertiary' title={type} style={{
maxWidth: maxTypeWidth,
}}>{type}</div>
{!isValidVar && <RiErrorWarningFill className='ml-0.5 h-3 w-3 text-text-destructive' />}
</>
)
: <div className={`overflow-hidden ${readonly ? 'text-components-input-text-disabled' : 'text-components-input-text-placeholder'} system-sm-regular text-ellipsis`}>
{isLoading ? (
<div className='flex items-center'>
<RiLoader4Line className='mr-1 h-3.5 w-3.5 animate-spin text-text-secondary' />
<span>{placeholder ?? t('workflow.common.setVarValuePlaceholder')}</span>
</div>
) : (
placeholder ?? t('workflow.common.setVarValuePlaceholder')
)}
</div>}
)
: (<div ref={!isSupportConstantValue ? triggerRef : null} className={cn((open || isFocus) ? 'border-gray-300' : 'border-gray-100', 'group/wrap relative flex h-8 w-full items-center', !isSupportConstantValue && 'rounded-lg bg-components-input-bg-normal p-1', isInTable && 'border-none bg-transparent', readonly && 'bg-components-input-bg-disabled')}>
{isSupportConstantValue
? <div onClick={(e) => {
e.stopPropagation()
setOpen(false)
setControlFocus(Date.now())
}} className='mr-1 flex h-full items-center space-x-1'>
<TypeSelector
noLeft
trigger={
<div className='radius-md flex h-8 items-center bg-components-input-bg-normal px-2'>
<div className='system-sm-regular mr-1 text-components-input-text-filled'>{varKindTypes.find(item => item.value === varKindType)?.label}</div>
<RiArrowDownSLine className='h-4 w-4 text-text-quaternary' />
</div>
</Tooltip>
</div>
}
popupClassName='top-8'
readonly={readonly}
value={varKindType}
options={varKindTypes}
onChange={handleVarKindTypeChange}
showChecked
/>
</div>
: (!hasValue && <div className='ml-1.5 mr-1'>
<Variable02 className={`h-4 w-4 ${readonly ? 'text-components-input-text-disabled' : 'text-components-input-text-placeholder'}`} />
</div>)}
{isConstant
? (
<ConstantField
value={value as string}
onChange={onChange as ((value: string | number, varKindType: VarKindType, varInfo?: Var) => void)}
schema={schemaWithDynamicSelect as CredentialFormSchema}
readonly={readonly}
isLoading={isLoading}
/>
)
: (
<VarPickerWrap
onClick={() => {
if (readonly)
return
!isConstant ? setOpen(!open) : setControlFocus(Date.now())
}}
className='h-full grow'
>
<div ref={isSupportConstantValue ? triggerRef : null} className={cn('h-full', isSupportConstantValue && 'flex items-center rounded-lg bg-components-panel-bg py-1 pl-1')}>
<Tooltip noDecoration={isShowAPart} popupContent={tooltipPopup}>
<div className={cn('h-full items-center rounded-[5px] px-1.5', hasValue ? 'inline-flex bg-components-badge-white-to-dark' : 'flex')}>
{hasValue
? (
<>
{isShowNodeName && !isEnv && !isChatVar && (
<div className='flex items-center' onClick={(e) => {
if (e.metaKey || e.ctrlKey) {
e.stopPropagation()
handleVariableJump(outputVarNode?.id)
}
}}>
<div className='h-3 px-[1px]'>
{outputVarNode?.type && <VarBlockIcon
className='!text-text-primary'
type={outputVarNode.type}
/>}
</div>
<div className='mx-0.5 truncate text-xs font-medium text-text-secondary' title={outputVarNode?.title} style={{
maxWidth: maxNodeNameWidth,
}}>{outputVarNode?.title}</div>
<Line3 className='mr-0.5'></Line3>
</div>
)}
{isShowAPart && (
<div className='flex items-center'>
<RiMoreLine className='h-3 w-3 text-text-secondary' />
<Line3 className='mr-0.5 text-divider-deep'></Line3>
</div>
)}
<div className='flex items-center text-text-accent'>
{isLoading && <RiLoader4Line className='h-3.5 w-3.5 animate-spin text-text-secondary' />}
<VariableIconWithColor
variableCategory={variableCategory}
isExceptionVariable={isException}
/>
<div className={cn('ml-0.5 truncate text-xs font-medium', isEnv && '!text-text-secondary', isChatVar && 'text-util-colors-teal-teal-700', isException && 'text-text-warning')} title={varName} style={{
maxWidth: maxVarNameWidth,
}}>{varName}</div>
</div>
<div className='system-xs-regular ml-0.5 truncate text-center capitalize text-text-tertiary' title={type} style={{
maxWidth: maxTypeWidth,
}}>{type}</div>
{!isValidVar && <RiErrorWarningFill className='ml-0.5 h-3 w-3 text-text-destructive' />}
</>
)
: <div className={`overflow-hidden ${readonly ? 'text-components-input-text-disabled' : 'text-components-input-text-placeholder'} system-sm-regular text-ellipsis`}>
{isLoading ? (
<div className='flex items-center'>
<RiLoader4Line className='mr-1 h-3.5 w-3.5 animate-spin text-text-secondary' />
<span>{placeholder ?? t('workflow.common.setVarValuePlaceholder')}</span>
</div>
) : (
placeholder ?? t('workflow.common.setVarValuePlaceholder')
)}
</div>}
</div>
</Tooltip>
</div>
</VarPickerWrap>
</VarPickerWrap>
)}
{(hasValue && !readonly && !isInTable) && (<div
className='group invisible absolute right-1 top-[50%] h-5 translate-y-[-50%] cursor-pointer rounded-md p-1 hover:bg-state-base-hover group-hover/wrap:visible'
onClick={handleClearVar}
>
<RiCloseLine className='h-3.5 w-3.5 text-text-tertiary group-hover:text-text-secondary' />
</div>)}
{!hasValue && valueTypePlaceHolder && (
<Badge
className=' absolute right-1 top-[50%] translate-y-[-50%] capitalize'
text={valueTypePlaceHolder}
uppercase={false}
/>
)}
{(hasValue && !readonly && !isInTable) && (<div
className='group invisible absolute right-1 top-[50%] h-5 translate-y-[-50%] cursor-pointer rounded-md p-1 hover:bg-state-base-hover group-hover/wrap:visible'
onClick={handleClearVar}
>
<RiCloseLine className='h-3.5 w-3.5 text-text-tertiary group-hover:text-text-secondary' />
</div>)}
{!hasValue && valueTypePlaceHolder && (
<Badge
className=' absolute right-1 top-[50%] translate-y-[-50%] capitalize'
text={valueTypePlaceHolder}
uppercase={false}
/>
)}
</div>)}
{!readonly && isInTable && (
<RemoveButton
className='absolute right-1 top-0.5 hidden group-hover/picker-trigger-wrap:block'
onClick={() => onRemove?.()}
/>
)}
{!readonly && isInTable && (
<RemoveButton
className='absolute right-1 top-0.5 hidden group-hover/picker-trigger-wrap:block'
onClick={() => onRemove?.()}
/>
)}
{!hasValue && typePlaceHolder && (
<Badge
className='absolute right-2 top-1.5'
text={typePlaceHolder}
uppercase={false}
/>
)}
</>
</WrapElem>
{!hasValue && typePlaceHolder && (
<Badge
className='absolute right-2 top-1.5'
text={typePlaceHolder}
uppercase={false}
/>
)}
</>
</WrapElem>
)}
<PortalToFollowElemContent style={{
zIndex: zIndex || 100,
}} className='mt-1'>