fix: when the variable does not exist, an error should be prompted (#8413)

Co-authored-by: Chen(MAC) <chenchen404@outlook.com>
This commit is contained in:
Pika 2024-09-14 14:08:10 +08:00 committed by GitHub
parent f01602b570
commit 5b18e851d2
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 100 additions and 67 deletions

View File

@ -1,9 +1,12 @@
import { useMemo } from 'react' import { useMemo } from 'react'
import { useNodes } from 'reactflow' import { useNodes } from 'reactflow'
import { capitalize } from 'lodash-es' import { capitalize } from 'lodash-es'
import { useTranslation } from 'react-i18next'
import { RiErrorWarningFill } from '@remixicon/react'
import { VarBlockIcon } from '@/app/components/workflow/block-icon' import { VarBlockIcon } from '@/app/components/workflow/block-icon'
import type { import type {
CommonNodeType, CommonNodeType,
Node,
ValueSelector, ValueSelector,
VarType, VarType,
} from '@/app/components/workflow/types' } from '@/app/components/workflow/types'
@ -11,63 +14,75 @@ import { BlockEnum } from '@/app/components/workflow/types'
import { Line3 } from '@/app/components/base/icons/src/public/common' import { Line3 } from '@/app/components/base/icons/src/public/common'
import { Variable02 } from '@/app/components/base/icons/src/vender/solid/development' import { Variable02 } from '@/app/components/base/icons/src/vender/solid/development'
import { BubbleX, Env } from '@/app/components/base/icons/src/vender/line/others' import { BubbleX, Env } from '@/app/components/base/icons/src/vender/line/others'
import { isConversationVar, isENV, isSystemVar } from '@/app/components/workflow/nodes/_base/components/variable/utils' import { getNodeInfoById, isConversationVar, isENV, isSystemVar } from '@/app/components/workflow/nodes/_base/components/variable/utils'
import Tooltip from '@/app/components/base/tooltip'
import cn from '@/utils/classnames' import cn from '@/utils/classnames'
type VariableTagProps = { type VariableTagProps = {
valueSelector: ValueSelector valueSelector: ValueSelector
varType: VarType varType: VarType
availableNodes?: Node[]
} }
const VariableTag = ({ const VariableTag = ({
valueSelector, valueSelector,
varType, varType,
availableNodes,
}: VariableTagProps) => { }: VariableTagProps) => {
const nodes = useNodes<CommonNodeType>() const nodes = useNodes<CommonNodeType>()
const node = useMemo(() => { const node = useMemo(() => {
if (isSystemVar(valueSelector)) if (isSystemVar(valueSelector)) {
return nodes.find(node => node.data.type === BlockEnum.Start) const startNode = availableNodes?.find(n => n.data.type === BlockEnum.Start)
if (startNode)
return startNode
}
return getNodeInfoById(availableNodes || nodes, valueSelector[0])
}, [nodes, valueSelector, availableNodes])
return nodes.find(node => node.id === valueSelector[0])
}, [nodes, valueSelector])
const isEnv = isENV(valueSelector) const isEnv = isENV(valueSelector)
const isChatVar = isConversationVar(valueSelector) const isChatVar = isConversationVar(valueSelector)
const isValid = Boolean(node) || isEnv || isChatVar
const variableName = isSystemVar(valueSelector) ? valueSelector.slice(0).join('.') : valueSelector.slice(1).join('.') const variableName = isSystemVar(valueSelector) ? valueSelector.slice(0).join('.') : valueSelector.slice(1).join('.')
const { t } = useTranslation()
return ( return (
<div className='inline-flex items-center px-1.5 max-w-full h-6 text-xs rounded-md border-[0.5px] border-[rgba(16, 2440,0.08)] bg-white shadow-xs'> <Tooltip popupContent={!isValid && t('workflow.errorMsg.invalidVariable')}>
{!isEnv && !isChatVar && ( <div className={cn('inline-flex items-center px-1.5 max-w-full h-6 text-xs rounded-md border-[0.5px] border-[rgba(16, 2440,0.08)] bg-white shadow-xs',
<> !isValid && 'border-red-400 !bg-[#FEF3F2]',
)}>
{(!isEnv && !isChatVar && <>
{node && ( {node && (
<VarBlockIcon <>
className='shrink-0 mr-0.5 text-text-secondary' <VarBlockIcon
type={node!.data.type} type={BlockEnum.Start}
/> />
<div
className='max-w-[60px] truncate text-text-secondary font-medium'
title={node?.data.title}
>
{node?.data.title}
</div>
</>
)} )}
<div
className='max-w-[60px] truncate text-text-secondary font-medium'
title={node?.data.title}
>
{node?.data.title}
</div>
<Line3 className='shrink-0 mx-0.5' /> <Line3 className='shrink-0 mx-0.5' />
<Variable02 className='shrink-0 mr-0.5 w-3.5 h-3.5 text-text-accent' /> <Variable02 className='shrink-0 mr-0.5 w-3.5 h-3.5 text-text-accent' />
</> </>)}
)} {isEnv && <Env className='shrink-0 mr-0.5 w-3.5 h-3.5 text-util-colors-violet-violet-600' />}
{isEnv && <Env className='shrink-0 mr-0.5 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' />}
{isChatVar && <BubbleX className='w-3.5 h-3.5 text-util-colors-teal-teal-700' />} <div
<div className={cn('truncate text-text-accent font-medium', (isEnv || isChatVar) && 'text-text-secondary')}
className={cn('truncate text-text-accent font-medium', (isEnv || isChatVar) && 'text-text-secondary')} title={variableName}
title={variableName} >
> {variableName}
{variableName} </div>
{
varType && (
<div className='shrink-0 ml-0.5 text-text-tertiary'>{capitalize(varType)}</div>
)
}
{!isValid && <RiErrorWarningFill className='ml-0.5 w-3 h-3 text-[#D92D20]' />}
</div> </div>
{ </Tooltip>
varType && (
<div className='shrink-0 ml-0.5 text-text-tertiary'>{capitalize(varType)}</div>
)
}
</div>
) )
} }

View File

@ -5,9 +5,10 @@ import { useTranslation } from 'react-i18next'
import { import {
RiArrowDownSLine, RiArrowDownSLine,
RiCloseLine, RiCloseLine,
RiErrorWarningFill,
} from '@remixicon/react' } from '@remixicon/react'
import produce from 'immer' import produce from 'immer'
import { useStoreApi } from 'reactflow' import { useEdges, useStoreApi } from 'reactflow'
import useAvailableVarList from '../../hooks/use-available-var-list' import useAvailableVarList from '../../hooks/use-available-var-list'
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'
@ -33,6 +34,8 @@ import { VarType as VarKindType } from '@/app/components/workflow/nodes/tool/typ
import TypeSelector from '@/app/components/workflow/nodes/_base/components/selector' import TypeSelector from '@/app/components/workflow/nodes/_base/components/selector'
import AddButton from '@/app/components/base/button/add-button' import AddButton from '@/app/components/base/button/add-button'
import Badge from '@/app/components/base/badge' import Badge from '@/app/components/base/badge'
import Tooltip from '@/app/components/base/tooltip'
const TRIGGER_DEFAULT_WIDTH = 227 const TRIGGER_DEFAULT_WIDTH = 227
type Props = { type Props = {
@ -77,6 +80,7 @@ const VarReferencePicker: FC<Props> = ({
const { const {
getNodes, getNodes,
} = store.getState() } = store.getState()
const edges = useEdges()
const isChatMode = useIsChatMode() const isChatMode = useIsChatMode()
const { getCurrentVariableType } = useWorkflowVariables() const { getCurrentVariableType } = useWorkflowVariables()
@ -206,8 +210,16 @@ const VarReferencePicker: FC<Props> = ({
isConstant: !!isConstant, isConstant: !!isConstant,
}) })
const isEnv = isENV(value as ValueSelector) const { isEnv, isChatVar, isValidVar } = useMemo(() => {
const isChatVar = isConversationVar(value as ValueSelector) const isEnv = isENV(value as ValueSelector)
const isChatVar = isConversationVar(value as ValueSelector)
const isValidVar = Boolean(outputVarNode) || isEnv || isChatVar
return {
isEnv,
isChatVar,
isValidVar,
}
}, [value, edges, outputVarNode])
// 8(left/right-padding) + 14(icon) + 4 + 14 + 2 = 42 + 17 buff // 8(left/right-padding) + 14(icon) + 4 + 14 + 2 = 42 + 17 buff
const availableWidth = triggerWidth - 56 const availableWidth = triggerWidth - 56
@ -285,39 +297,44 @@ const VarReferencePicker: FC<Props> = ({
className='grow h-full' 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 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')}> <Tooltip popupContent={!isValidVar && hasValue && t('workflow.errorMsg.invalidVariable')}>
{hasValue <div className={cn('h-full items-center px-1.5 rounded-[5px] ', hasValue ? 'bg-white inline-flex' : 'flex',
? ( !isValidVar && hasValue && 'border border-red-400 !bg-[#FEF3F2]',
<> )}>
{isShowNodeName && !isEnv && !isChatVar && ( {hasValue
<div className='flex items-center'> ? (
<div className='p-[1px]'> <>
<VarBlockIcon {isShowNodeName && !isEnv && !isChatVar && (
className='!text-gray-900' <div className='flex items-center'>
type={outputVarNode?.type || BlockEnum.Start} <div className='px-[1px] h-3'>
/> {outputVarNode?.type && <VarBlockIcon
className='!text-gray-900'
type={outputVarNode.type}
/>}
</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' />} {!isValidVar && <RiErrorWarningFill className='ml-0.5 w-3 h-3 text-[#D92D20]' /> }
{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, : <div className='text-[13px] font-normal text-gray-400'>{t('workflow.common.setVarValuePlaceholder')}</div>}
}}>{varName}</div> </div>
</div> </Tooltip>
<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>

View File

@ -80,6 +80,7 @@ const ConditionItem = ({
<VariableTag <VariableTag
valueSelector={condition.variable_selector} valueSelector={condition.variable_selector}
varType={condition.varType} varType={condition.varType}
availableNodes={availableNodes}
/> />
</div> </div>
<div className='mx-1 w-[1px] h-3 bg-divider-regular'></div> <div className='mx-1 w-[1px] h-3 bg-divider-regular'></div>