| @@ -10,10 +10,6 @@ import { | |||
| } from 'lexical' | |||
| import { mergeRegister } from '@lexical/utils' | |||
| import { useLexicalComposerContext } from '@lexical/react/LexicalComposerContext' | |||
| import { | |||
| RiErrorWarningFill, | |||
| RiMoreLine, | |||
| } from '@remixicon/react' | |||
| import { useReactFlow, useStoreApi } from 'reactflow' | |||
| import { useSelectOrDelete } from '../../hooks' | |||
| import type { WorkflowNodesMap } from './node' | |||
| @@ -22,17 +18,15 @@ import { | |||
| DELETE_WORKFLOW_VARIABLE_BLOCK_COMMAND, | |||
| UPDATE_WORKFLOW_NODES_MAP, | |||
| } from './index' | |||
| import cn from '@/utils/classnames' | |||
| import { Variable02 } from '@/app/components/base/icons/src/vender/solid/development' | |||
| import { BubbleX, Env } from '@/app/components/base/icons/src/vender/line/others' | |||
| import { VarBlockIcon } from '@/app/components/workflow/block-icon' | |||
| import { Line3 } from '@/app/components/base/icons/src/public/common' | |||
| import { isConversationVar, isENV, isSystemVar } from '@/app/components/workflow/nodes/_base/components/variable/utils' | |||
| import Tooltip from '@/app/components/base/tooltip' | |||
| import { isExceptionVariable } from '@/app/components/workflow/utils' | |||
| import VarFullPathPanel from '@/app/components/workflow/nodes/_base/components/variable/var-full-path-panel' | |||
| import { Type } from '@/app/components/workflow/nodes/llm/types' | |||
| import type { ValueSelector, Var } from '@/app/components/workflow/types' | |||
| import { | |||
| VariableLabelInEditor, | |||
| } from '@/app/components/workflow/nodes/_base/components/variable/variable-label' | |||
| type WorkflowVariableBlockComponentProps = { | |||
| nodeKey: string | |||
| @@ -126,69 +120,22 @@ const WorkflowVariableBlockComponent = ({ | |||
| }, [node, reactflow, store]) | |||
| const Item = ( | |||
| <div | |||
| className={cn( | |||
| 'group/wrap relative mx-0.5 flex h-[18px] select-none items-center rounded-[5px] border pl-0.5 pr-[3px] hover:border-state-accent-solid hover:bg-state-accent-hover', | |||
| isSelected ? ' border-state-accent-solid bg-state-accent-hover' : ' border-components-panel-border-subtle bg-components-badge-white-to-dark', | |||
| !variableValid && '!border-state-destructive-solid !bg-state-destructive-hover', | |||
| )} | |||
| <VariableLabelInEditor | |||
| nodeType={node?.type} | |||
| nodeTitle={node?.title} | |||
| variables={variables} | |||
| onClick={(e) => { | |||
| e.stopPropagation() | |||
| handleVariableJump() | |||
| }} | |||
| isExceptionVariable={isException} | |||
| errorMsg={!variableValid ? t('workflow.errorMsg.invalidVariable') : undefined} | |||
| isSelected={isSelected} | |||
| ref={ref} | |||
| > | |||
| {!isEnv && !isChatVar && ( | |||
| <div className='flex items-center'> | |||
| { | |||
| node?.type && ( | |||
| <div className='p-[1px]'> | |||
| <VarBlockIcon | |||
| className='!text-text-secondary' | |||
| type={node?.type} | |||
| /> | |||
| </div> | |||
| ) | |||
| } | |||
| <div className='mx-0.5 max-w-[60px] shrink-0 truncate text-xs font-medium text-text-secondary' title={node?.title} style={{ | |||
| }}>{node?.title}</div> | |||
| <Line3 className='mr-0.5 text-divider-deep'></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'> | |||
| {!isEnv && !isChatVar && <Variable02 className={cn('h-3.5 w-3.5 shrink-0', isException && 'text-text-warning')} />} | |||
| {isEnv && <Env className='h-3.5 w-3.5 shrink-0 text-util-colors-violet-violet-600' />} | |||
| {isChatVar && <BubbleX className='h-3.5 w-3.5 text-util-colors-teal-teal-700' />} | |||
| <div className={cn( | |||
| 'ml-0.5 shrink-0 truncate text-xs font-medium', | |||
| isEnv && 'text-util-colors-violet-violet-600', | |||
| isChatVar && 'text-util-colors-teal-teal-700', | |||
| isException && 'text-text-warning', | |||
| )} title={varName}>{varName}</div> | |||
| { | |||
| !variableValid && ( | |||
| <RiErrorWarningFill className='ml-0.5 h-3 w-3 text-text-destructive' /> | |||
| ) | |||
| } | |||
| </div> | |||
| </div> | |||
| notShowFullPath={isShowAPart} | |||
| /> | |||
| ) | |||
| if (!variableValid) { | |||
| return ( | |||
| <Tooltip popupContent={t('workflow.errorMsg.invalidVariable')}> | |||
| {Item} | |||
| </Tooltip> | |||
| ) | |||
| } | |||
| if (!node) | |||
| return Item | |||
| @@ -4,12 +4,10 @@ import React from 'react' | |||
| import cn from 'classnames' | |||
| import { useWorkflow } from '../../../hooks' | |||
| import { BlockEnum } from '../../../types' | |||
| import { VarBlockIcon } from '../../../block-icon' | |||
| import { getNodeInfoById, isConversationVar, isENV, isSystemVar } from './variable/utils' | |||
| import { Line3 } from '@/app/components/base/icons/src/public/common' | |||
| import { Variable02 } from '@/app/components/base/icons/src/vender/solid/development' | |||
| import { BubbleX, Env } from '@/app/components/base/icons/src/vender/line/others' | |||
| import { RiMoreLine } from '@remixicon/react' | |||
| import { getNodeInfoById, isSystemVar } from './variable/utils' | |||
| import { | |||
| VariableLabelInText, | |||
| } from '@/app/components/workflow/nodes/_base/components/variable/variable-label' | |||
| type Props = { | |||
| nodeId: string | |||
| value: string | |||
| @@ -42,40 +40,17 @@ const ReadonlyInputWithSelectVar: FC<Props> = ({ | |||
| const value = vars[index].split('.') | |||
| const isSystem = isSystemVar(value) | |||
| const isEnv = isENV(value) | |||
| const isChatVar = isConversationVar(value) | |||
| const node = (isSystem ? startNode : getNodeInfoById(availableNodes, value[0]))?.data | |||
| const varName = `${isSystem ? 'sys.' : ''}${value[value.length - 1]}` | |||
| const isShowAPart = value.length > 2 | |||
| return (<span key={index}> | |||
| <span className='relative top-[-3px] leading-[16px]'>{str}</span> | |||
| <div className=' inline-flex h-[16px] items-center rounded-[5px] bg-components-badge-white-to-dark px-1.5'> | |||
| {!isEnv && !isChatVar && ( | |||
| <div className='flex items-center'> | |||
| <div className='p-[1px]'> | |||
| <VarBlockIcon | |||
| className='!text-text-primary' | |||
| type={node?.type || BlockEnum.Start} | |||
| /> | |||
| </div> | |||
| <div className='mx-0.5 max-w-[60px] truncate text-xs font-medium text-text-secondary' title={node?.title}>{node?.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'> | |||
| {!isEnv && !isChatVar && <Variable02 className='h-3.5 w-3.5 shrink-0' />} | |||
| {isEnv && <Env className='h-3.5 w-3.5 shrink-0 text-util-colors-violet-violet-600' />} | |||
| {isChatVar && <BubbleX className='h-3.5 w-3.5 text-util-colors-teal-teal-700' />} | |||
| <div className={cn('ml-0.5 max-w-[50px] truncate text-xs font-medium', (isEnv || isChatVar) && 'text-text-primary')} title={varName}>{varName}</div> | |||
| </div> | |||
| </div> | |||
| <VariableLabelInText | |||
| nodeTitle={node?.title} | |||
| nodeType={node?.type} | |||
| notShowFullPath={isShowAPart} | |||
| variables={value} | |||
| /> | |||
| </span>) | |||
| }) | |||
| return html | |||
| @@ -1,9 +1,6 @@ | |||
| import { useCallback, useMemo } from 'react' | |||
| import { useNodes, useReactFlow, useStoreApi } from 'reactflow' | |||
| import { capitalize } from 'lodash-es' | |||
| import { useTranslation } from 'react-i18next' | |||
| import { RiErrorWarningFill } from '@remixicon/react' | |||
| import { VarBlockIcon } from '@/app/components/workflow/block-icon' | |||
| import type { | |||
| CommonNodeType, | |||
| Node, | |||
| @@ -11,13 +8,11 @@ import type { | |||
| VarType, | |||
| } from '@/app/components/workflow/types' | |||
| import { BlockEnum } from '@/app/components/workflow/types' | |||
| import { Line3 } from '@/app/components/base/icons/src/public/common' | |||
| import { Variable02 } from '@/app/components/base/icons/src/vender/solid/development' | |||
| import { BubbleX, Env } from '@/app/components/base/icons/src/vender/line/others' | |||
| 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 { isExceptionVariable } from '@/app/components/workflow/utils' | |||
| import { | |||
| VariableLabelInSelect, | |||
| } from '@/app/components/workflow/nodes/_base/components/variable/variable-label' | |||
| type VariableTagProps = { | |||
| valueSelector: ValueSelector | |||
| @@ -73,51 +68,20 @@ const VariableTag = ({ | |||
| const { t } = useTranslation() | |||
| return ( | |||
| <Tooltip popupContent={!isValid && t('workflow.errorMsg.invalidVariable')}> | |||
| <div className={cn('border-[rgba(16, 2440,0.08)] inline-flex h-6 max-w-full items-center rounded-md border-[0.5px] border-divider-subtle bg-components-badge-white-to-dark px-1.5 text-xs shadow-xs', | |||
| !isValid && 'border-red-400 !bg-[#FEF3F2]', | |||
| )} | |||
| onClick={(e) => { | |||
| if (e.metaKey || e.ctrlKey) { | |||
| e.stopPropagation() | |||
| handleVariableJump() | |||
| } | |||
| }} | |||
| > | |||
| {(!isEnv && !isChatVar && <> | |||
| {node && ( | |||
| <> | |||
| <VarBlockIcon | |||
| type={node.data.type || BlockEnum.Start} | |||
| className='mr-0.5 !text-text-primary' | |||
| /> | |||
| <div | |||
| className='max-w-[60px] truncate font-medium text-text-secondary' | |||
| title={node?.data.title} | |||
| > | |||
| {node?.data.title} | |||
| </div> | |||
| </> | |||
| )} | |||
| <Line3 className='mx-0.5 shrink-0' /> | |||
| <Variable02 className={cn('mr-0.5 h-3.5 w-3.5 shrink-0 text-text-accent', isException && 'text-text-warning')} /> | |||
| </>)} | |||
| {isEnv && <Env className='mr-0.5 h-3.5 w-3.5 shrink-0 text-util-colors-violet-violet-600' />} | |||
| {isChatVar && <BubbleX className='h-3.5 w-3.5 text-util-colors-teal-teal-700' />} | |||
| <div | |||
| className={cn('ml-0.5 truncate font-medium text-text-accent', (isEnv || isChatVar) && 'text-text-secondary', isException && 'text-text-warning')} | |||
| title={variableName} | |||
| > | |||
| {variableName} | |||
| </div> | |||
| { | |||
| !isShort && varType && ( | |||
| <div className='ml-0.5 shrink-0 text-text-tertiary'>{capitalize(varType)}</div> | |||
| ) | |||
| <VariableLabelInSelect | |||
| variables={valueSelector} | |||
| nodeType={node?.data.type} | |||
| nodeTitle={node?.data.title} | |||
| variableType={!isShort ? varType : undefined} | |||
| onClick={(e) => { | |||
| if (e.metaKey || e.ctrlKey) { | |||
| e.stopPropagation() | |||
| handleVariableJump() | |||
| } | |||
| {!isValid && <RiErrorWarningFill className='ml-0.5 h-3 w-3 text-[#D92D20]' />} | |||
| </div> | |||
| </Tooltip> | |||
| }} | |||
| errorMsg={!isValid ? t('workflow.errorMsg.invalidVariable') : undefined} | |||
| isExceptionVariable={isException} | |||
| /> | |||
| ) | |||
| } | |||
| @@ -23,7 +23,6 @@ import { type CredentialFormSchema, type FormOption, FormTypeEnum } from '@/app/ | |||
| import { BlockEnum } from '@/app/components/workflow/types' | |||
| import { VarBlockIcon } from '@/app/components/workflow/block-icon' | |||
| import { Line3 } from '@/app/components/base/icons/src/public/common' | |||
| import { BubbleX, Env } from '@/app/components/base/icons/src/vender/line/others' | |||
| import { Variable02 } from '@/app/components/base/icons/src/vender/solid/development' | |||
| import { | |||
| PortalToFollowElem, | |||
| @@ -44,6 +43,7 @@ import VarFullPathPanel from './var-full-path-panel' | |||
| import { noop } from 'lodash-es' | |||
| import { useFetchDynamicOptions } from '@/service/use-plugins' | |||
| import type { Tool } from '@/app/components/tools/types' | |||
| import { VariableIconWithColor } from '@/app/components/workflow/nodes/_base/components/variable/variable-label' | |||
| const TRIGGER_DEFAULT_WIDTH = 227 | |||
| @@ -138,7 +138,6 @@ const VarReferencePicker: FC<Props> = ({ | |||
| useEffect(() => { | |||
| if (triggerRef.current) | |||
| setTriggerWidth(triggerRef.current.clientWidth) | |||
| // eslint-disable-next-line react-hooks/exhaustive-deps | |||
| }, [triggerRef.current]) | |||
| const [varKindType, setVarKindType] = useState<VarKindType>(defaultVarKindType) | |||
| @@ -149,7 +148,6 @@ const VarReferencePicker: FC<Props> = ({ | |||
| const [open, setOpen] = useState(false) | |||
| useEffect(() => { | |||
| onOpen() | |||
| // eslint-disable-next-line react-hooks/exhaustive-deps | |||
| }, [open]) | |||
| const hasValue = !isConstant && value.length > 0 | |||
| @@ -362,6 +360,13 @@ const VarReferencePicker: FC<Props> = ({ | |||
| return schema | |||
| }, [dynamicOptions]) | |||
| const variableCategory = useMemo(() => { | |||
| if (isEnv) return 'environment' | |||
| if (isChatVar) return 'conversation' | |||
| if (isLoopVar) return 'loop' | |||
| return 'system' | |||
| }, [isEnv, isChatVar, isLoopVar]) | |||
| return ( | |||
| <div className={cn(className, !readonly && 'cursor-pointer')}> | |||
| <PortalToFollowElem | |||
| @@ -458,10 +463,11 @@ const VarReferencePicker: FC<Props> = ({ | |||
| </div> | |||
| )} | |||
| <div className='flex items-center text-text-accent'> | |||
| {!hasValue && <Variable02 className='h-3.5 w-3.5' />} | |||
| {isLoading && <RiLoader4Line className='h-3.5 w-3.5 animate-spin text-text-secondary' />} | |||
| {isEnv && <Env className='h-3.5 w-3.5 text-util-colors-violet-violet-600' />} | |||
| {isChatVar && <BubbleX className='h-3.5 w-3.5 text-util-colors-teal-teal-700' />} | |||
| <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> | |||
| @@ -5,7 +5,6 @@ import { useHover } from 'ahooks' | |||
| import { useTranslation } from 'react-i18next' | |||
| import cn from '@/utils/classnames' | |||
| import { type NodeOutPutVar, type ValueSelector, type Var, VarType } from '@/app/components/workflow/types' | |||
| import { Variable02 } from '@/app/components/base/icons/src/vender/solid/development' | |||
| import { ChevronRight } from '@/app/components/base/icons/src/vender/line/arrows' | |||
| import { | |||
| PortalToFollowElem, | |||
| @@ -13,7 +12,6 @@ import { | |||
| PortalToFollowElemTrigger, | |||
| } from '@/app/components/base/portal-to-follow-elem' | |||
| import Input from '@/app/components/base/input' | |||
| import { BubbleX, Env } from '@/app/components/base/icons/src/vender/line/others' | |||
| import { checkKeys } from '@/utils/var' | |||
| import type { StructuredOutput } from '../../../llm/types' | |||
| import { Type } from '../../../llm/types' | |||
| @@ -21,8 +19,8 @@ import PickerStructurePanel from '@/app/components/workflow/nodes/_base/componen | |||
| import { varTypeToStructType } from './utils' | |||
| import type { Field } from '@/app/components/workflow/nodes/llm/types' | |||
| import { FILE_STRUCT } from '@/app/components/workflow/constants' | |||
| import { Loop } from '@/app/components/base/icons/src/vender/workflow' | |||
| import { noop } from 'lodash-es' | |||
| import { VariableIconWithColor } from '@/app/components/workflow/nodes/_base/components/variable/variable-label' | |||
| type ObjectChildrenProps = { | |||
| nodeId: string | |||
| @@ -118,7 +116,6 @@ const Item: FC<ItemProps> = ({ | |||
| const open = (isObj || isStructureOutput) && isHovering | |||
| useEffect(() => { | |||
| onHovering && onHovering(isHovering) | |||
| // eslint-disable-next-line react-hooks/exhaustive-deps | |||
| }, [isHovering]) | |||
| const handleChosen = (e: React.MouseEvent) => { | |||
| e.stopPropagation() | |||
| @@ -132,6 +129,12 @@ const Item: FC<ItemProps> = ({ | |||
| onChange([nodeId, ...objPath, itemData.variable], itemData) | |||
| } | |||
| } | |||
| const variableCategory = useMemo(() => { | |||
| if (isEnv) return 'environment' | |||
| if (isChatVar) return 'conversation' | |||
| if (isLoopVar) return 'loop' | |||
| return 'system' | |||
| }, [isEnv, isChatVar, isSys, isLoopVar]) | |||
| return ( | |||
| <PortalToFollowElem | |||
| open={open} | |||
| @@ -150,10 +153,10 @@ const Item: FC<ItemProps> = ({ | |||
| onMouseDown={e => e.preventDefault()} | |||
| > | |||
| <div className='flex w-0 grow items-center'> | |||
| {!isEnv && !isChatVar && !isLoopVar && <Variable02 className={cn('h-3.5 w-3.5 shrink-0 text-text-accent', isException && 'text-text-warning')} />} | |||
| {isEnv && <Env className='h-3.5 w-3.5 shrink-0 text-util-colors-violet-violet-600' />} | |||
| {isChatVar && <BubbleX className='h-3.5 w-3.5 shrink-0 text-util-colors-teal-teal-700' />} | |||
| {isLoopVar && <Loop className='h-3.5 w-3.5 shrink-0 text-util-colors-cyan-cyan-500' />} | |||
| <VariableIconWithColor | |||
| variableCategory={variableCategory} | |||
| isExceptionVariable={isException} | |||
| /> | |||
| {!isEnv && !isChatVar && ( | |||
| <div title={itemData.variable} className='system-sm-medium ml-1 w-0 grow truncate text-text-secondary'>{itemData.variable}</div> | |||
| )} | |||
| @@ -219,11 +222,9 @@ const ObjectChildren: FC<ObjectChildrenProps> = ({ | |||
| const isHovering = isItemHovering || isChildrenHovering | |||
| useEffect(() => { | |||
| onHovering && onHovering(isHovering) | |||
| // eslint-disable-next-line react-hooks/exhaustive-deps | |||
| }, [isHovering]) | |||
| useEffect(() => { | |||
| onHovering && onHovering(isItemHovering) | |||
| // eslint-disable-next-line react-hooks/exhaustive-deps | |||
| }, [isItemHovering]) | |||
| // absolute top-[-2px] | |||
| return ( | |||
| @@ -0,0 +1,28 @@ | |||
| import { memo } from 'react' | |||
| import cn from '@/utils/classnames' | |||
| import { useVarIcon } from '../hooks' | |||
| import type { VarInInspectType } from '@/types/workflow' | |||
| export type VariableIconProps = { | |||
| className?: string | |||
| variables?: string[] | |||
| variableCategory?: VarInInspectType | string | |||
| } | |||
| const VariableIcon = ({ | |||
| className, | |||
| variables = [], | |||
| variableCategory, | |||
| }: VariableIconProps) => { | |||
| const VarIcon = useVarIcon(variables, variableCategory) | |||
| return VarIcon && ( | |||
| <VarIcon | |||
| className={cn( | |||
| 'size-3.5 shrink-0', | |||
| className, | |||
| )} | |||
| /> | |||
| ) | |||
| } | |||
| export default memo(VariableIcon) | |||
| @@ -0,0 +1,83 @@ | |||
| import { memo } from 'react' | |||
| import { capitalize } from 'lodash-es' | |||
| import { | |||
| RiErrorWarningFill, | |||
| RiMoreLine, | |||
| } from '@remixicon/react' | |||
| import type { VariablePayload } from '../types' | |||
| import { useVarColor } from '../hooks' | |||
| import VariableNodeLabel from './variable-node-label' | |||
| import VariableIcon from './variable-icon' | |||
| import VariableName from './variable-name' | |||
| import cn from '@/utils/classnames' | |||
| import Tooltip from '@/app/components/base/tooltip' | |||
| const VariableLabel = ({ | |||
| nodeType, | |||
| nodeTitle, | |||
| variables, | |||
| variableType, | |||
| className, | |||
| errorMsg, | |||
| onClick, | |||
| isExceptionVariable, | |||
| ref, | |||
| notShowFullPath, | |||
| rightSlot, | |||
| }: VariablePayload) => { | |||
| const varColorClassName = useVarColor(variables, isExceptionVariable) | |||
| return ( | |||
| <div | |||
| className={cn( | |||
| 'inline-flex h-6 max-w-full items-center space-x-0.5 rounded-md border-[0.5px] border-components-panel-border-subtle bg-components-badge-white-to-dark px-1.5 shadow-xs', | |||
| className, | |||
| )} | |||
| onClick={onClick} | |||
| ref={ref} | |||
| > | |||
| <VariableNodeLabel | |||
| nodeType={nodeType} | |||
| nodeTitle={nodeTitle} | |||
| /> | |||
| { | |||
| notShowFullPath && ( | |||
| <> | |||
| <RiMoreLine className='h-3 w-3 shrink-0 text-text-secondary' /> | |||
| <div className='system-xs-regular shrink-0 text-divider-deep'>/</div> | |||
| </> | |||
| ) | |||
| } | |||
| <VariableIcon | |||
| variables={variables} | |||
| className={varColorClassName} | |||
| /> | |||
| <VariableName | |||
| variables={variables} | |||
| className={cn(varColorClassName)} | |||
| notShowFullPath={notShowFullPath} | |||
| /> | |||
| { | |||
| variableType && ( | |||
| <div className='system-xs-regular shrink-0 text-text-tertiary'> | |||
| {capitalize(variableType)} | |||
| </div> | |||
| ) | |||
| } | |||
| { | |||
| !!errorMsg && ( | |||
| <Tooltip | |||
| popupContent={errorMsg} | |||
| asChild | |||
| > | |||
| <RiErrorWarningFill className='h-3 w-3 shrink-0 text-text-destructive' /> | |||
| </Tooltip> | |||
| ) | |||
| } | |||
| { | |||
| rightSlot | |||
| } | |||
| </div> | |||
| ) | |||
| } | |||
| export default memo(VariableLabel) | |||
| @@ -0,0 +1,30 @@ | |||
| import { memo } from 'react' | |||
| import { useVarName } from '../hooks' | |||
| import cn from '@/utils/classnames' | |||
| type VariableNameProps = { | |||
| variables: string[] | |||
| className?: string | |||
| notShowFullPath?: boolean | |||
| } | |||
| const VariableName = ({ | |||
| variables, | |||
| className, | |||
| notShowFullPath, | |||
| }: VariableNameProps) => { | |||
| const varName = useVarName(variables, notShowFullPath) | |||
| return ( | |||
| <div | |||
| className={cn( | |||
| 'system-xs-medium truncate', | |||
| className, | |||
| )} | |||
| title={varName} | |||
| > | |||
| {varName} | |||
| </div> | |||
| ) | |||
| } | |||
| export default memo(VariableName) | |||
| @@ -0,0 +1,37 @@ | |||
| import { memo } from 'react' | |||
| import { VarBlockIcon } from '@/app/components/workflow/block-icon' | |||
| import type { BlockEnum } from '@/app/components/workflow/types' | |||
| type VariableNodeLabelProps = { | |||
| nodeType?: BlockEnum | |||
| nodeTitle?: string | |||
| } | |||
| const VariableNodeLabel = ({ | |||
| nodeType, | |||
| nodeTitle, | |||
| }: VariableNodeLabelProps) => { | |||
| if (!nodeType) | |||
| return null | |||
| return ( | |||
| <> | |||
| <VarBlockIcon | |||
| type={nodeType} | |||
| className='shrink-0 text-text-secondary' | |||
| /> | |||
| { | |||
| nodeTitle && ( | |||
| <div | |||
| className='system-xs-medium max-[60px] truncate text-text-secondary' | |||
| title={nodeTitle} | |||
| > | |||
| {nodeTitle} | |||
| </div> | |||
| ) | |||
| } | |||
| <div className='system-xs-regular shrink-0 text-divider-deep'>/</div> | |||
| </> | |||
| ) | |||
| } | |||
| export default memo(VariableNodeLabel) | |||
| @@ -0,0 +1,89 @@ | |||
| import { useMemo } from 'react' | |||
| import { Variable02 } from '@/app/components/base/icons/src/vender/solid/development' | |||
| import { BubbleX, Env } from '@/app/components/base/icons/src/vender/line/others' | |||
| import { Loop } from '@/app/components/base/icons/src/vender/workflow' | |||
| import { | |||
| isConversationVar, | |||
| isENV, | |||
| isSystemVar, | |||
| } from '../utils' | |||
| import { VarInInspectType } from '@/types/workflow' | |||
| export const useVarIcon = (variables: string[], variableCategory?: VarInInspectType | string) => { | |||
| if (variableCategory === 'loop') | |||
| return Loop | |||
| if (isENV(variables) || variableCategory === VarInInspectType.environment || variableCategory === 'environment') | |||
| return Env | |||
| if (isConversationVar(variables) || variableCategory === VarInInspectType.conversation || variableCategory === 'conversation') | |||
| return BubbleX | |||
| return Variable02 | |||
| } | |||
| export const useVarColor = (variables: string[], isExceptionVariable?: boolean, variableCategory?: VarInInspectType | string) => { | |||
| return useMemo(() => { | |||
| if (isExceptionVariable) | |||
| return 'text-text-warning' | |||
| if (variableCategory === 'loop') | |||
| return 'text-util-colors-cyan-cyan-500' | |||
| if (isENV(variables) || variableCategory === VarInInspectType.environment || variableCategory === 'environment') | |||
| return 'text-util-colors-violet-violet-600' | |||
| if (isConversationVar(variables) || variableCategory === VarInInspectType.conversation || variableCategory === 'conversation') | |||
| return 'text-util-colors-teal-teal-700' | |||
| return 'text-text-accent' | |||
| }, [variables, isExceptionVariable]) | |||
| } | |||
| export const useVarName = (variables: string[], notShowFullPath?: boolean) => { | |||
| const variableFullPathName = variables.slice(1).join('.') | |||
| const variablesLength = variables.length | |||
| const varName = useMemo(() => { | |||
| const isSystem = isSystemVar(variables) | |||
| const varName = notShowFullPath ? variables[variablesLength - 1] : variableFullPathName | |||
| return `${isSystem ? 'sys.' : ''}${varName}` | |||
| }, [variables, notShowFullPath]) | |||
| return varName | |||
| } | |||
| export const useVarBgColorInEditor = (variables: string[], hasError?: boolean) => { | |||
| if (hasError) { | |||
| return { | |||
| hoverBorderColor: 'hover:border-state-destructive-active', | |||
| hoverBgColor: 'hover:bg-state-destructive-hover', | |||
| selectedBorderColor: '!border-state-destructive-solid', | |||
| selectedBgColor: '!bg-state-destructive-hover', | |||
| } | |||
| } | |||
| if (isENV(variables)) { | |||
| return { | |||
| hoverBorderColor: 'hover:border-util-colors-violet-violet-100', | |||
| hoverBgColor: 'hover:bg-util-colors-violet-violet-50', | |||
| selectedBorderColor: 'border-util-colors-violet-violet-600', | |||
| selectedBgColor: 'bg-util-colors-violet-violet-50', | |||
| } | |||
| } | |||
| if (isConversationVar(variables)) { | |||
| return { | |||
| hoverBorderColor: 'hover:border-util-colors-teal-teal-100', | |||
| hoverBgColor: 'hover:bg-util-colors-teal-teal-50', | |||
| selectedBorderColor: 'border-util-colors-teal-teal-600', | |||
| selectedBgColor: 'bg-util-colors-teal-teal-50', | |||
| } | |||
| } | |||
| return { | |||
| hoverBorderColor: 'hover:border-state-accent-alt', | |||
| hoverBgColor: 'hover:bg-state-accent-hover', | |||
| selectedBorderColor: 'border-state-accent-solid', | |||
| selectedBgColor: 'bg-state-accent-hover', | |||
| } | |||
| } | |||
| @@ -0,0 +1,5 @@ | |||
| export { default as VariableLabelInSelect } from './variable-label-in-select' | |||
| export { default as VariableLabelInEditor } from './variable-label-in-editor' | |||
| export { default as VariableLabelInNode } from './variable-label-in-node' | |||
| export { default as VariableLabelInText } from './variable-label-in-text' | |||
| export { default as VariableIconWithColor } from './variable-icon-with-color' | |||
| @@ -0,0 +1,19 @@ | |||
| import type { ReactNode } from 'react' | |||
| import type { | |||
| BlockEnum, | |||
| VarType, | |||
| } from '@/app/components/workflow/types' | |||
| export type VariablePayload = { | |||
| className?: string | |||
| nodeType?: BlockEnum | |||
| nodeTitle?: string | |||
| variables: string[] | |||
| variableType?: VarType | |||
| onClick?: (e: React.MouseEvent<HTMLDivElement>) => void | |||
| errorMsg?: string | |||
| isExceptionVariable?: boolean | |||
| ref?: React.Ref<HTMLDivElement> | |||
| notShowFullPath?: boolean | |||
| rightSlot?: ReactNode | |||
| } | |||
| @@ -0,0 +1,30 @@ | |||
| import { memo } from 'react' | |||
| import VariableIcon from './base/variable-icon' | |||
| import type { VariableIconProps } from './base/variable-icon' | |||
| import { useVarColor } from './hooks' | |||
| import cn from '@/utils/classnames' | |||
| type VariableIconWithColorProps = { | |||
| isExceptionVariable?: boolean | |||
| } & VariableIconProps | |||
| const VariableIconWithColor = ({ | |||
| isExceptionVariable, | |||
| variableCategory, | |||
| variables = [], | |||
| className, | |||
| }: VariableIconWithColorProps) => { | |||
| const varColorClassName = useVarColor(variables, isExceptionVariable, variableCategory) | |||
| return ( | |||
| <VariableIcon | |||
| variables={variables} | |||
| variableCategory={variableCategory} | |||
| className={cn( | |||
| varColorClassName, | |||
| className, | |||
| )} | |||
| /> | |||
| ) | |||
| } | |||
| export default memo(VariableIconWithColor) | |||
| @@ -0,0 +1,40 @@ | |||
| import { memo } from 'react' | |||
| import type { VariablePayload } from './types' | |||
| import VariableLabel from './base/variable-label' | |||
| import { useVarBgColorInEditor } from './hooks' | |||
| import cn from '@/utils/classnames' | |||
| type VariableLabelInEditorProps = { | |||
| isSelected?: boolean | |||
| } & VariablePayload | |||
| const VariableLabelInEditor = ({ | |||
| isSelected, | |||
| variables, | |||
| errorMsg, | |||
| ...rest | |||
| }: VariableLabelInEditorProps) => { | |||
| const { | |||
| hoverBorderColor, | |||
| hoverBgColor, | |||
| selectedBorderColor, | |||
| selectedBgColor, | |||
| } = useVarBgColorInEditor(variables, !!errorMsg) | |||
| return ( | |||
| <VariableLabel | |||
| className={cn( | |||
| 'h-[18px] space-x-[1px] rounded-[5px] px-1 shadow-xs', | |||
| !isSelected && hoverBgColor, | |||
| !isSelected && hoverBorderColor, | |||
| isSelected && 'border', | |||
| isSelected && selectedBorderColor, | |||
| isSelected && selectedBgColor, | |||
| )} | |||
| variables={variables} | |||
| errorMsg={errorMsg} | |||
| {...rest} | |||
| /> | |||
| ) | |||
| } | |||
| export default memo(VariableLabelInEditor) | |||
| @@ -0,0 +1,17 @@ | |||
| import { memo } from 'react' | |||
| import type { VariablePayload } from './types' | |||
| import VariableLabel from './base/variable-label' | |||
| import cn from '@/utils/classnames' | |||
| const VariableLabelInNode = (variablePayload: VariablePayload) => { | |||
| return ( | |||
| <VariableLabel | |||
| className={cn( | |||
| 'w-full space-x-[1px] bg-workflow-block-parma-bg px-1 shadow-none', | |||
| )} | |||
| {...variablePayload} | |||
| /> | |||
| ) | |||
| } | |||
| export default memo(VariableLabelInNode) | |||
| @@ -0,0 +1,13 @@ | |||
| import { memo } from 'react' | |||
| import type { VariablePayload } from './types' | |||
| import VariableLabel from './base/variable-label' | |||
| const VariableLabelInSelect = (variablePayload: VariablePayload) => { | |||
| return ( | |||
| <VariableLabel | |||
| {...variablePayload} | |||
| /> | |||
| ) | |||
| } | |||
| export default memo(VariableLabelInSelect) | |||
| @@ -0,0 +1,17 @@ | |||
| import { memo } from 'react' | |||
| import type { VariablePayload } from './types' | |||
| import VariableLabel from './base/variable-label' | |||
| import cn from '@/utils/classnames' | |||
| const VariableLabelInText = (variablePayload: VariablePayload) => { | |||
| return ( | |||
| <VariableLabel | |||
| className={cn( | |||
| 'h-[18px] space-x-[1px] rounded-[5px] px-1 shadow-xs', | |||
| )} | |||
| {...variablePayload} | |||
| /> | |||
| ) | |||
| } | |||
| export default memo(VariableLabelInText) | |||
| @@ -2,10 +2,13 @@ import type { FC } from 'react' | |||
| import React from 'react' | |||
| import { useNodes } from 'reactflow' | |||
| import { useTranslation } from 'react-i18next' | |||
| import NodeVariableItem from '../variable-assigner/components/node-variable-item' | |||
| import type { AssignerNodeType } from './types' | |||
| import { isConversationVar, isENV, isSystemVar } from '@/app/components/workflow/nodes/_base/components/variable/utils' | |||
| import { isSystemVar } from '@/app/components/workflow/nodes/_base/components/variable/utils' | |||
| import { BlockEnum, type Node, type NodeProps } from '@/app/components/workflow/types' | |||
| import { | |||
| VariableLabelInNode, | |||
| } from '@/app/components/workflow/nodes/_base/components/variable/variable-label' | |||
| import Badge from '@/app/components/base/badge' | |||
| const i18nPrefix = 'workflow.nodes.assigner' | |||
| @@ -38,19 +41,16 @@ const NodeComponent: FC<NodeProps<AssignerNodeType>> = ({ | |||
| if (!variable || variable.length === 0) | |||
| return null | |||
| const isSystem = isSystemVar(variable) | |||
| const isEnv = isENV(variable) | |||
| const isChatVar = isConversationVar(variable) | |||
| const node = isSystem ? nodes.find(node => node.data.type === BlockEnum.Start) : nodes.find(node => node.id === variable[0]) | |||
| const varName = isSystem ? `sys.${variable[variable.length - 1]}` : variable.slice(1).join('.') | |||
| return ( | |||
| <NodeVariableItem | |||
| <VariableLabelInNode | |||
| key={index} | |||
| node={node as Node} | |||
| isEnv={isEnv} | |||
| isChatVar={isChatVar} | |||
| writeMode={value.operation} | |||
| varName={varName} | |||
| className='bg-workflow-block-parma-bg' | |||
| variables={variable} | |||
| nodeType={node?.data.type} | |||
| nodeTitle={node?.data.title} | |||
| rightSlot={ | |||
| value.operation && <Badge className='!ml-auto shrink-0' text={t(`${i18nPrefix}.operations.${value.operation}`)} /> | |||
| } | |||
| /> | |||
| ) | |||
| })} | |||
| @@ -63,21 +63,17 @@ const NodeComponent: FC<NodeProps<AssignerNodeType>> = ({ | |||
| if (!variable || variable.length === 0) | |||
| return null | |||
| const isSystem = isSystemVar(variable) | |||
| const isEnv = isENV(variable) | |||
| const isChatVar = isConversationVar(variable) | |||
| const node = isSystem ? nodes.find(node => node.data.type === BlockEnum.Start) : nodes.find(node => node.id === variable[0]) | |||
| const varName = isSystem ? `sys.${variable[variable.length - 1]}` : variable.slice(1).join('.') | |||
| return ( | |||
| <div className='relative flex flex-col items-start gap-0.5 self-stretch px-3 py-1'> | |||
| <NodeVariableItem | |||
| node={node as Node} | |||
| isEnv={isEnv} | |||
| isChatVar={isChatVar} | |||
| varName={varName} | |||
| writeMode={writeMode} | |||
| className='bg-workflow-block-parma-bg' | |||
| <VariableLabelInNode | |||
| variables={variable} | |||
| nodeType={node?.data.type} | |||
| nodeTitle={node?.data.title} | |||
| rightSlot={ | |||
| writeMode && <Badge className='!ml-auto shrink-0' text={t(`${i18nPrefix}.operations.${writeMode}`)} /> | |||
| } | |||
| /> | |||
| </div> | |||
| ) | |||
| @@ -2,10 +2,12 @@ import type { FC } from 'react' | |||
| import React from 'react' | |||
| import { useNodes } from 'reactflow' | |||
| import { useTranslation } from 'react-i18next' | |||
| import NodeVariableItem from '../variable-assigner/components/node-variable-item' | |||
| import type { DocExtractorNodeType } from './types' | |||
| import { isConversationVar, isENV, isSystemVar } from '@/app/components/workflow/nodes/_base/components/variable/utils' | |||
| import { isSystemVar } from '@/app/components/workflow/nodes/_base/components/variable/utils' | |||
| import { BlockEnum, type Node, type NodeProps } from '@/app/components/workflow/types' | |||
| import { | |||
| VariableLabelInNode, | |||
| } from '@/app/components/workflow/nodes/_base/components/variable/variable-label' | |||
| const i18nPrefix = 'workflow.nodes.docExtractor' | |||
| @@ -21,19 +23,14 @@ const NodeComponent: FC<NodeProps<DocExtractorNodeType>> = ({ | |||
| return null | |||
| const isSystem = isSystemVar(variable) | |||
| const isEnv = isENV(variable) | |||
| const isChatVar = isConversationVar(variable) | |||
| const node = isSystem ? nodes.find(node => node.data.type === BlockEnum.Start) : nodes.find(node => node.id === variable[0]) | |||
| const varName = isSystem ? `sys.${variable[variable.length - 1]}` : variable.slice(1).join('.') | |||
| return ( | |||
| <div className='relative px-3'> | |||
| <div className='system-2xs-medium-uppercase mb-1 text-text-tertiary'>{t(`${i18nPrefix}.inputVar`)}</div> | |||
| <NodeVariableItem | |||
| node={node as Node} | |||
| isEnv={isEnv} | |||
| isChatVar={isChatVar} | |||
| varName={varName} | |||
| className='bg-workflow-block-parma-bg' | |||
| <VariableLabelInNode | |||
| variables={variable} | |||
| nodeType={node?.data.type} | |||
| nodeTitle={node?.data.title} | |||
| /> | |||
| </div> | |||
| ) | |||
| @@ -1,19 +1,16 @@ | |||
| import type { FC } from 'react' | |||
| import React from 'react' | |||
| import cn from 'classnames' | |||
| import type { EndNodeType } from './types' | |||
| import type { NodeProps, Variable } from '@/app/components/workflow/types' | |||
| import { isConversationVar, isENV, isSystemVar } from '@/app/components/workflow/nodes/_base/components/variable/utils' | |||
| import { | |||
| useIsChatMode, | |||
| useWorkflow, | |||
| useWorkflowVariables, | |||
| } from '@/app/components/workflow/hooks' | |||
| import { VarBlockIcon } from '@/app/components/workflow/block-icon' | |||
| import { Line3 } from '@/app/components/base/icons/src/public/common' | |||
| import { Variable02 } from '@/app/components/base/icons/src/vender/solid/development' | |||
| import { BubbleX, Env } from '@/app/components/base/icons/src/vender/line/others' | |||
| import { BlockEnum } from '@/app/components/workflow/types' | |||
| import { | |||
| VariableLabelInNode, | |||
| } from '@/app/components/workflow/nodes/_base/components/variable/variable-label' | |||
| const Node: FC<NodeProps<EndNodeType>> = ({ | |||
| id, | |||
| @@ -42,42 +39,20 @@ const Node: FC<NodeProps<EndNodeType>> = ({ | |||
| <div className='mb-1 space-y-0.5 px-3 py-1'> | |||
| {filteredOutputs.map(({ value_selector }, index) => { | |||
| const node = getNode(value_selector[0]) | |||
| const isSystem = isSystemVar(value_selector) | |||
| const isEnv = isENV(value_selector) | |||
| const isChatVar = isConversationVar(value_selector) | |||
| const varName = isSystem ? `sys.${value_selector[value_selector.length - 1]}` : value_selector[value_selector.length - 1] | |||
| const varType = getCurrentVariableType({ | |||
| valueSelector: value_selector, | |||
| availableNodes, | |||
| isChatMode, | |||
| }) | |||
| return ( | |||
| <div key={index} className='flex h-6 items-center justify-between space-x-1 rounded-md bg-workflow-block-parma-bg px-1 text-xs font-normal text-text-secondary'> | |||
| <div className='flex items-center text-xs font-medium text-text-tertiary'> | |||
| {!isEnv && !isChatVar && ( | |||
| <> | |||
| <div className='p-[1px]'> | |||
| <VarBlockIcon | |||
| className='!text-text-primary' | |||
| type={node?.data.type || BlockEnum.Start} | |||
| /> | |||
| </div> | |||
| <div className='max-w-[75px] truncate'>{node?.data.title}</div> | |||
| <Line3 className='mr-0.5'></Line3> | |||
| </> | |||
| )} | |||
| <div className='flex items-center text-text-accent'> | |||
| {!isEnv && !isChatVar && <Variable02 className='h-3.5 w-3.5 shrink-0 text-text-accent' />} | |||
| {isEnv && <Env className='h-3.5 w-3.5 shrink-0 text-util-colors-violet-violet-600' />} | |||
| {isChatVar && <BubbleX className='h-3.5 w-3.5 text-util-colors-teal-teal-700' />} | |||
| <div className={cn('ml-0.5 max-w-[50px] truncate text-xs font-medium', (isEnv || isChatVar) && '!max-w-[70px] text-text-primary')}>{varName}</div> | |||
| </div> | |||
| </div> | |||
| <div className='text-xs font-normal text-text-secondary'> | |||
| <div className='ml-0.5 max-w-[42px] truncate text-xs font-normal capitalize text-text-tertiary' title={varType}>{varType}</div> | |||
| </div> | |||
| </div> | |||
| return ( | |||
| <VariableLabelInNode | |||
| key={index} | |||
| variables={value_selector} | |||
| nodeType={node?.data.type} | |||
| nodeTitle={node?.data.title} | |||
| variableType={varType} | |||
| /> | |||
| ) | |||
| })} | |||
| @@ -15,7 +15,7 @@ const Node: FC<NodeProps<HttpNodeType>> = ({ | |||
| <div className='mb-1 px-3 py-1'> | |||
| <div className='flex items-center justify-start rounded-md bg-workflow-block-parma-bg p-1'> | |||
| <div className='flex h-4 shrink-0 items-center rounded bg-components-badge-white-to-dark px-1 text-xs font-semibold uppercase text-text-secondary'>{method}</div> | |||
| <div className='pl-1 pt-1'> | |||
| <div className='w-0 grow pl-1 pt-1'> | |||
| <ReadonlyInputWithSelectVar | |||
| className='text-text-secondary' | |||
| value={url} | |||
| @@ -11,10 +11,10 @@ import { | |||
| } from '../utils' | |||
| import { FILE_TYPE_OPTIONS, TRANSFER_METHOD } from '../../constants' | |||
| import type { ValueSelector } from '../../../types' | |||
| import { Variable02 } from '@/app/components/base/icons/src/vender/solid/development' | |||
| import { BubbleX, Env } from '@/app/components/base/icons/src/vender/line/others' | |||
| import cn from '@/utils/classnames' | |||
| import { isConversationVar, isENV, isSystemVar } from '@/app/components/workflow/nodes/_base/components/variable/utils' | |||
| import { isSystemVar } from '@/app/components/workflow/nodes/_base/components/variable/utils' | |||
| import { | |||
| VariableLabelInNode, | |||
| } from '@/app/components/workflow/nodes/_base/components/variable/variable-label' | |||
| const i18nPrefix = 'workflow.nodes.ifElse' | |||
| type ConditionValueProps = { | |||
| @@ -32,11 +32,7 @@ const ConditionValue = ({ | |||
| const variableSelector = variable_selector as ValueSelector | |||
| const variableName = (isSystemVar(variableSelector) ? variableSelector.slice(0).join('.') : variableSelector.slice(1).join('.')) | |||
| const operatorName = isComparisonOperatorNeedTranslate(operator) ? t(`workflow.nodes.ifElse.comparisonOperator.${operator}`) : operator | |||
| const notHasValue = comparisonOperatorNotRequireValue(operator) | |||
| const isEnvVar = isENV(variableSelector) | |||
| const isChatVar = isConversationVar(variableSelector) | |||
| const formatValue = useCallback((c: Condition) => { | |||
| const notHasValue = comparisonOperatorNotRequireValue(c.comparison_operator) | |||
| if (notHasValue) | |||
| @@ -76,19 +72,11 @@ const ConditionValue = ({ | |||
| return ( | |||
| <div className='rounded-md bg-workflow-block-parma-bg'> | |||
| <div className='flex h-6 items-center px-1 '> | |||
| {!isEnvVar && !isChatVar && <Variable02 className='mr-1 h-3.5 w-3.5 shrink-0 text-text-accent' />} | |||
| {isEnvVar && <Env className='mr-1 h-3.5 w-3.5 shrink-0 text-util-colors-violet-violet-600' />} | |||
| {isChatVar && <BubbleX className='h-3.5 w-3.5 text-util-colors-teal-teal-700' />} | |||
| <div | |||
| className={cn( | |||
| 'shrink-0 truncate text-xs font-medium text-text-accent', | |||
| !notHasValue && 'max-w-[70px]', | |||
| )} | |||
| title={variableName} | |||
| > | |||
| {variableName} | |||
| </div> | |||
| <VariableLabelInNode | |||
| className='w-0 grow' | |||
| variables={variableSelector} | |||
| notShowFullPath | |||
| /> | |||
| <div | |||
| className='mx-1 shrink-0 text-xs font-medium text-text-primary' | |||
| title={operatorName} | |||
| @@ -10,15 +10,15 @@ import { | |||
| isComparisonOperatorNeedTranslate, | |||
| } from '../utils' | |||
| import { FILE_TYPE_OPTIONS, TRANSFER_METHOD } from '../../constants' | |||
| import { Variable02 } from '@/app/components/base/icons/src/vender/solid/development' | |||
| import { BubbleX, Env } from '@/app/components/base/icons/src/vender/line/others' | |||
| import cn from '@/utils/classnames' | |||
| import { isConversationVar, isENV, isSystemVar } from '@/app/components/workflow/nodes/_base/components/variable/utils' | |||
| import { isSystemVar } from '@/app/components/workflow/nodes/_base/components/variable/utils' | |||
| import { isExceptionVariable } from '@/app/components/workflow/utils' | |||
| import type { | |||
| CommonNodeType, | |||
| Node, | |||
| } from '@/app/components/workflow/types' | |||
| import { | |||
| VariableLabelInText, | |||
| } from '@/app/components/workflow/nodes/_base/components/variable/variable-label' | |||
| type ConditionValueProps = { | |||
| variableSelector: string[] | |||
| @@ -37,8 +37,6 @@ const ConditionValue = ({ | |||
| const variableName = labelName || (isSystemVar(variableSelector) ? variableSelector.slice(0).join('.') : variableSelector.slice(1).join('.')) | |||
| const operatorName = isComparisonOperatorNeedTranslate(operator) ? t(`workflow.nodes.ifElse.comparisonOperator.${operator}`) : operator | |||
| const notHasValue = comparisonOperatorNotRequireValue(operator) | |||
| const isEnvVar = isENV(variableSelector) | |||
| const isChatVar = isConversationVar(variableSelector) | |||
| const node: Node<CommonNodeType> | undefined = nodes.find(n => n.id === variableSelector[0]) as Node<CommonNodeType> | |||
| const isException = isExceptionVariable(variableName, node?.data.type) | |||
| const formatValue = useMemo(() => { | |||
| @@ -76,20 +74,14 @@ const ConditionValue = ({ | |||
| return ( | |||
| <div className='flex h-6 items-center rounded-md bg-workflow-block-parma-bg px-1'> | |||
| {!isEnvVar && !isChatVar && <Variable02 className={cn('mr-1 h-3.5 w-3.5 shrink-0 text-text-accent', isException && 'text-text-warning')} />} | |||
| {isEnvVar && <Env className='mr-1 h-3.5 w-3.5 shrink-0 text-util-colors-violet-violet-600' />} | |||
| {isChatVar && <BubbleX className='h-3.5 w-3.5 shrink-0 text-util-colors-teal-teal-700' />} | |||
| <div | |||
| className={cn( | |||
| 'ml-0.5 shrink-[2] truncate text-xs font-medium text-text-accent', | |||
| !notHasValue && 'max-w-[70px]', | |||
| isException && 'text-text-warning', | |||
| )} | |||
| title={variableName} | |||
| > | |||
| {variableName} | |||
| </div> | |||
| <VariableLabelInText | |||
| className='w-0 grow' | |||
| variables={variableSelector} | |||
| nodeTitle={node?.data.title} | |||
| nodeType={node?.data.type} | |||
| isExceptionVariable={isException} | |||
| notShowFullPath | |||
| /> | |||
| <div | |||
| className='mx-1 shrink-0 text-xs font-medium text-text-primary' | |||
| title={operatorName} | |||
| @@ -2,10 +2,12 @@ import type { FC } from 'react' | |||
| import React from 'react' | |||
| import { useNodes } from 'reactflow' | |||
| import { useTranslation } from 'react-i18next' | |||
| import NodeVariableItem from '../variable-assigner/components/node-variable-item' | |||
| import type { ListFilterNodeType } from './types' | |||
| import { isConversationVar, isENV, isSystemVar } from '@/app/components/workflow/nodes/_base/components/variable/utils' | |||
| import { isSystemVar } from '@/app/components/workflow/nodes/_base/components/variable/utils' | |||
| import { BlockEnum, type Node, type NodeProps } from '@/app/components/workflow/types' | |||
| import { | |||
| VariableLabelInNode, | |||
| } from '@/app/components/workflow/nodes/_base/components/variable/variable-label' | |||
| const i18nPrefix = 'workflow.nodes.listFilter' | |||
| @@ -21,19 +23,14 @@ const NodeComponent: FC<NodeProps<ListFilterNodeType>> = ({ | |||
| return null | |||
| const isSystem = isSystemVar(variable) | |||
| const isEnv = isENV(variable) | |||
| const isChatVar = isConversationVar(variable) | |||
| const node = isSystem ? nodes.find(node => node.data.type === BlockEnum.Start) : nodes.find(node => node.id === variable[0]) | |||
| const varName = isSystem ? `sys.${variable[variable.length - 1]}` : variable.slice(1).join('.') | |||
| return ( | |||
| <div className='relative px-3'> | |||
| <div className='system-2xs-medium-uppercase mb-1 text-text-tertiary'>{t(`${i18nPrefix}.inputVar`)}</div> | |||
| <NodeVariableItem | |||
| node={node as Node} | |||
| isEnv={isEnv} | |||
| isChatVar={isChatVar} | |||
| varName={varName} | |||
| className='bg-workflow-block-parma-bg' | |||
| <VariableLabelInNode | |||
| variables={variable} | |||
| nodeType={node?.data.type} | |||
| nodeTitle={node?.data.title} | |||
| /> | |||
| </div> | |||
| ) | |||
| @@ -11,10 +11,10 @@ import { | |||
| } from '../utils' | |||
| import type { ValueSelector } from '../../../types' | |||
| import { FILE_TYPE_OPTIONS, TRANSFER_METHOD } from './../default' | |||
| import { Variable02 } from '@/app/components/base/icons/src/vender/solid/development' | |||
| import { BubbleX, Env } from '@/app/components/base/icons/src/vender/line/others' | |||
| import cn from '@/utils/classnames' | |||
| import { isConversationVar, isENV, isSystemVar } from '@/app/components/workflow/nodes/_base/components/variable/utils' | |||
| import { isSystemVar } from '@/app/components/workflow/nodes/_base/components/variable/utils' | |||
| import { | |||
| VariableLabelInNode, | |||
| } from '@/app/components/workflow/nodes/_base/components/variable/variable-label' | |||
| const i18nPrefix = 'workflow.nodes.ifElse' | |||
| type ConditionValueProps = { | |||
| @@ -32,11 +32,7 @@ const ConditionValue = ({ | |||
| const variableSelector = variable_selector as ValueSelector | |||
| const variableName = (isSystemVar(variableSelector) ? variableSelector.slice(0).join('.') : variableSelector.slice(1).join('.')) | |||
| const operatorName = isComparisonOperatorNeedTranslate(operator) ? t(`workflow.nodes.ifElse.comparisonOperator.${operator}`) : operator | |||
| const notHasValue = comparisonOperatorNotRequireValue(operator) | |||
| const isEnvVar = isENV(variableSelector) | |||
| const isChatVar = isConversationVar(variableSelector) | |||
| const formatValue = useCallback((c: Condition) => { | |||
| const notHasValue = comparisonOperatorNotRequireValue(c.comparison_operator) | |||
| if (notHasValue) | |||
| @@ -76,19 +72,11 @@ const ConditionValue = ({ | |||
| return ( | |||
| <div className='rounded-md bg-workflow-block-parma-bg'> | |||
| <div className='flex h-6 items-center px-1 '> | |||
| {!isEnvVar && !isChatVar && <Variable02 className='mr-1 h-3.5 w-3.5 shrink-0 text-text-accent' />} | |||
| {isEnvVar && <Env className='mr-1 h-3.5 w-3.5 shrink-0 text-util-colors-violet-violet-600' />} | |||
| {isChatVar && <BubbleX className='h-3.5 w-3.5 text-util-colors-teal-teal-700' />} | |||
| <div | |||
| className={cn( | |||
| 'shrink-0 truncate text-xs font-medium text-text-accent', | |||
| !notHasValue && 'max-w-[70px]', | |||
| )} | |||
| title={variableName} | |||
| > | |||
| {variableName} | |||
| </div> | |||
| <VariableLabelInNode | |||
| className='w-0 grow' | |||
| variables={variableSelector} | |||
| notShowFullPath | |||
| /> | |||
| <div | |||
| className='mx-1 shrink-0 text-xs font-medium text-text-primary' | |||
| title={operatorName} | |||
| @@ -9,10 +9,10 @@ import { | |||
| isComparisonOperatorNeedTranslate, | |||
| } from '../utils' | |||
| import { FILE_TYPE_OPTIONS, TRANSFER_METHOD } from './../default' | |||
| import { Variable02 } from '@/app/components/base/icons/src/vender/solid/development' | |||
| import { BubbleX, Env } from '@/app/components/base/icons/src/vender/line/others' | |||
| import cn from '@/utils/classnames' | |||
| import { isConversationVar, isENV, isSystemVar } from '@/app/components/workflow/nodes/_base/components/variable/utils' | |||
| import { isSystemVar } from '@/app/components/workflow/nodes/_base/components/variable/utils' | |||
| import { | |||
| VariableLabelInNode, | |||
| } from '@/app/components/workflow/nodes/_base/components/variable/variable-label' | |||
| type ConditionValueProps = { | |||
| variableSelector: string[] | |||
| @@ -27,11 +27,8 @@ const ConditionValue = ({ | |||
| value, | |||
| }: ConditionValueProps) => { | |||
| const { t } = useTranslation() | |||
| const variableName = labelName || (isSystemVar(variableSelector) ? variableSelector.slice(0).join('.') : variableSelector.slice(1).join('.')) | |||
| const operatorName = isComparisonOperatorNeedTranslate(operator) ? t(`workflow.nodes.ifElse.comparisonOperator.${operator}`) : operator | |||
| const notHasValue = comparisonOperatorNotRequireValue(operator) | |||
| const isEnvVar = isENV(variableSelector) | |||
| const isChatVar = isConversationVar(variableSelector) | |||
| const formatValue = useMemo(() => { | |||
| if (notHasValue) | |||
| return '' | |||
| @@ -67,19 +64,11 @@ const ConditionValue = ({ | |||
| return ( | |||
| <div className='flex h-6 items-center rounded-md bg-workflow-block-parma-bg px-1'> | |||
| {!isEnvVar && !isChatVar && <Variable02 className='mr-1 h-3.5 w-3.5 shrink-0 text-text-accent' />} | |||
| {isEnvVar && <Env className='mr-1 h-3.5 w-3.5 shrink-0 text-util-colors-violet-violet-600' />} | |||
| {isChatVar && <BubbleX className='h-3.5 w-3.5 text-util-colors-teal-teal-700' />} | |||
| <div | |||
| className={cn( | |||
| 'shrink-0 truncate text-xs font-medium text-text-accent', | |||
| !notHasValue && 'max-w-[70px]', | |||
| )} | |||
| title={variableName} | |||
| > | |||
| {variableName} | |||
| </div> | |||
| <VariableLabelInNode | |||
| className='w-0 grow' | |||
| variables={variableSelector} | |||
| notShowFullPath | |||
| /> | |||
| <div | |||
| className='mx-1 shrink-0 text-xs font-medium text-text-primary' | |||
| title={operatorName} | |||
| @@ -18,10 +18,12 @@ import { | |||
| } from '../hooks' | |||
| import { filterVar } from '../utils' | |||
| import AddVariable from './add-variable' | |||
| import NodeVariableItem from './node-variable-item' | |||
| import { isConversationVar, isENV, isSystemVar } from '@/app/components/workflow/nodes/_base/components/variable/utils' | |||
| import { isSystemVar } from '@/app/components/workflow/nodes/_base/components/variable/utils' | |||
| import cn from '@/utils/classnames' | |||
| import { isExceptionVariable } from '@/app/components/workflow/utils' | |||
| import { | |||
| VariableLabelInNode, | |||
| } from '@/app/components/workflow/nodes/_base/components/variable/variable-label' | |||
| const i18nPrefix = 'workflow.nodes.variableAssigner' | |||
| type GroupItem = { | |||
| @@ -122,27 +124,29 @@ const NodeGroupItem = ({ | |||
| ) | |||
| } | |||
| { | |||
| !!item.variables.length && item.variables.map((variable = [], index) => { | |||
| const isSystem = isSystemVar(variable) | |||
| const isEnv = isENV(variable) | |||
| const isChatVar = isConversationVar(variable) | |||
| !!item.variables.length && ( | |||
| <div className='space-y-0.5'> | |||
| { | |||
| item.variables.map((variable = [], index) => { | |||
| const isSystem = isSystemVar(variable) | |||
| const node = isSystem ? nodes.find(node => node.data.type === BlockEnum.Start) : nodes.find(node => node.id === variable[0]) | |||
| const varName = isSystem ? `sys.${variable[variable.length - 1]}` : variable.slice(1).join('.') | |||
| const isException = isExceptionVariable(varName, node?.data.type) | |||
| const node = isSystem ? nodes.find(node => node.data.type === BlockEnum.Start) : nodes.find(node => node.id === variable[0]) | |||
| const varName = isSystem ? `sys.${variable[variable.length - 1]}` : variable.slice(1).join('.') | |||
| const isException = isExceptionVariable(varName, node?.data.type) | |||
| return ( | |||
| <NodeVariableItem | |||
| key={index} | |||
| isEnv={isEnv} | |||
| isChatVar={isChatVar} | |||
| isException={isException} | |||
| node={node as Node} | |||
| varName={varName} | |||
| showBorder={showSelectedBorder || showSelectionBorder} | |||
| /> | |||
| ) | |||
| }) | |||
| return ( | |||
| <VariableLabelInNode | |||
| key={index} | |||
| variables={variable} | |||
| nodeType={node?.data.type} | |||
| nodeTitle={node?.data.title} | |||
| isExceptionVariable={isException} | |||
| /> | |||
| ) | |||
| }) | |||
| } | |||
| </div> | |||
| ) | |||
| } | |||
| </div> | |||
| ) | |||
| @@ -1,111 +0,0 @@ | |||
| import { | |||
| memo, | |||
| useMemo, | |||
| } from 'react' | |||
| import { useTranslation } from 'react-i18next' | |||
| import cn from '@/utils/classnames' | |||
| import { VarBlockIcon } from '@/app/components/workflow/block-icon' | |||
| import { Line3 } from '@/app/components/base/icons/src/public/common' | |||
| import { Variable02 } from '@/app/components/base/icons/src/vender/solid/development' | |||
| import { BubbleX, Env } from '@/app/components/base/icons/src/vender/line/others' | |||
| import Badge from '@/app/components/base/badge' | |||
| import type { Node } from '@/app/components/workflow/types' | |||
| type NodeVariableItemProps = { | |||
| isEnv: boolean | |||
| isChatVar: boolean | |||
| node: Node | |||
| varName: string | |||
| writeMode?: string | |||
| showBorder?: boolean | |||
| className?: string | |||
| isException?: boolean | |||
| } | |||
| const i18nPrefix = 'workflow.nodes.assigner' | |||
| const NodeVariableItem = ({ | |||
| isEnv, | |||
| isChatVar, | |||
| node, | |||
| varName, | |||
| writeMode, | |||
| showBorder, | |||
| className, | |||
| isException, | |||
| }: NodeVariableItemProps) => { | |||
| const { t } = useTranslation() | |||
| const VariableIcon = useMemo(() => { | |||
| if (isEnv) { | |||
| return ( | |||
| <Env className='h-3.5 w-3.5 shrink-0 text-util-colors-violet-violet-600' /> | |||
| ) | |||
| } | |||
| if (isChatVar) { | |||
| return ( | |||
| <BubbleX className='h-3.5 w-3.5 shrink-0 text-util-colors-teal-teal-700' /> | |||
| ) | |||
| } | |||
| return ( | |||
| <Variable02 | |||
| className={cn( | |||
| 'h-3.5 w-3.5 shrink-0 text-text-accent', | |||
| isException && 'text-text-warning', | |||
| )} | |||
| /> | |||
| ) | |||
| }, [isEnv, isChatVar, isException]) | |||
| const VariableName = useMemo(() => { | |||
| return ( | |||
| <div | |||
| className={cn( | |||
| 'system-xs-medium ml-0.5 shrink truncate text-text-accent', | |||
| isEnv && 'text-text-primary', | |||
| isException && 'text-text-warning', | |||
| isChatVar && 'text-util-colors-teal-teal-700', | |||
| )} | |||
| title={varName} | |||
| > | |||
| {varName} | |||
| </div> | |||
| ) | |||
| }, [isEnv, isChatVar, varName, isException]) | |||
| return ( | |||
| <div className={cn( | |||
| 'relative flex items-center gap-1 self-stretch rounded-md bg-workflow-block-parma-bg p-[3px] pl-[5px]', | |||
| showBorder && '!bg-state-base-hover', | |||
| className, | |||
| )}> | |||
| <div className='flex w-0 grow items-center'> | |||
| { | |||
| node && ( | |||
| <> | |||
| <div className='shrink-0 p-[1px]'> | |||
| <VarBlockIcon | |||
| className='!text-text-primary' | |||
| type={node.data.type} | |||
| /> | |||
| </div> | |||
| <div | |||
| className='mx-0.5 shrink-[1000] truncate text-xs font-medium text-text-secondary' | |||
| title={node?.data.title} | |||
| > | |||
| {node?.data.title} | |||
| </div> | |||
| <Line3 className='mr-0.5 shrink-0'></Line3> | |||
| </> | |||
| ) | |||
| } | |||
| {VariableIcon} | |||
| {VariableName} | |||
| </div> | |||
| {writeMode && <Badge className='shrink-0' text={t(`${i18nPrefix}.operations.${writeMode}`)} />} | |||
| </div> | |||
| ) | |||
| } | |||
| export default memo(NodeVariableItem) | |||
| @@ -11,16 +11,12 @@ import { | |||
| import ActionButton from '@/app/components/base/action-button' | |||
| import Tooltip from '@/app/components/base/tooltip' | |||
| import BlockIcon from '@/app/components/workflow/block-icon' | |||
| import { | |||
| BubbleX, | |||
| Env, | |||
| } from '@/app/components/base/icons/src/vender/line/others' | |||
| import { Variable02 } from '@/app/components/base/icons/src/vender/solid/development' | |||
| import type { currentVarType } from './panel' | |||
| import { VarInInspectType } from '@/types/workflow' | |||
| import type { NodeWithVar, VarInInspect } from '@/types/workflow' | |||
| import cn from '@/utils/classnames' | |||
| import { useToolIcon } from '../hooks' | |||
| import { VariableIconWithColor } from '@/app/components/workflow/nodes/_base/components/variable/variable-label' | |||
| type Props = { | |||
| nodeData?: NodeWithVar | |||
| @@ -158,9 +154,11 @@ const Group = ({ | |||
| )} | |||
| onClick={() => handleSelectVar(varItem, varType)} | |||
| > | |||
| {isEnv && <Env className='h-4 w-4 shrink-0 text-util-colors-violet-violet-600' />} | |||
| {isChatVar && <BubbleX className='h-4 w-4 shrink-0 text-util-colors-teal-teal-700' />} | |||
| {(isSystem || nodeData) && <Variable02 className={cn('h-4 w-4 shrink-0 text-text-accent', ['error_type', 'error_message'].includes(varItem.name) && 'text-text-warning')} />} | |||
| <VariableIconWithColor | |||
| variableCategory={varType} | |||
| isExceptionVariable={['error_type', 'error_message'].includes(varItem.name)} | |||
| className='size-4' | |||
| /> | |||
| <div className='system-sm-medium grow truncate text-text-secondary'>{varItem.name}</div> | |||
| <div className='system-xs-regular shrink-0 text-text-tertiary'>{varItem.value_type}</div> | |||
| </div> | |||
| @@ -14,12 +14,11 @@ import Badge from '@/app/components/base/badge' | |||
| import CopyFeedback from '@/app/components/base/copy-feedback' | |||
| import Tooltip from '@/app/components/base/tooltip' | |||
| import BlockIcon from '@/app/components/workflow/block-icon' | |||
| import { BubbleX, Env } from '@/app/components/base/icons/src/vender/line/others' | |||
| import { Variable02 } from '@/app/components/base/icons/src/vender/solid/development' | |||
| import Loading from '@/app/components/base/loading' | |||
| import type { currentVarType } from './panel' | |||
| import { VarInInspectType } from '@/types/workflow' | |||
| import cn from '@/utils/classnames' | |||
| import { VariableIconWithColor } from '@/app/components/workflow/nodes/_base/components/variable/variable-label' | |||
| type Props = { | |||
| currentNodeVar?: currentVarType | |||
| @@ -86,15 +85,14 @@ const Right = ({ | |||
| <div className='flex w-0 grow items-center gap-1'> | |||
| {currentNodeVar && ( | |||
| <> | |||
| {currentNodeVar.nodeType === VarInInspectType.environment && ( | |||
| <Env className='h-4 w-4 shrink-0 text-util-colors-violet-violet-600' /> | |||
| )} | |||
| {currentNodeVar.nodeType === VarInInspectType.conversation && ( | |||
| <BubbleX className='h-4 w-4 shrink-0 text-util-colors-teal-teal-700' /> | |||
| )} | |||
| {currentNodeVar.nodeType === VarInInspectType.system && ( | |||
| <Variable02 className='h-4 w-4 shrink-0 text-text-accent' /> | |||
| )} | |||
| { | |||
| [VarInInspectType.environment, VarInInspectType.conversation, VarInInspectType.system].includes(currentNodeVar.nodeType as VarInInspectType) && ( | |||
| <VariableIconWithColor | |||
| variableCategory={currentNodeVar.nodeType as VarInInspectType} | |||
| className='size-4' | |||
| /> | |||
| ) | |||
| } | |||
| {currentNodeVar.nodeType !== VarInInspectType.environment && currentNodeVar.nodeType !== VarInInspectType.conversation && currentNodeVar.nodeType !== VarInInspectType.system && ( | |||
| <> | |||
| <BlockIcon | |||