chore(web): new lint setup (#30020)

Co-authored-by: yyh <yuanyouhuilyz@gmail.com>
This commit is contained in:
Stephen Zhou
2025-12-23 16:58:55 +08:00
committed by GitHub
parent 9701a2994b
commit f2842da397
3356 changed files with 85046 additions and 81278 deletions

View File

@ -1,26 +1,26 @@
import type { LoopNodeType } from './types'
import type {
OnSelectBlock,
} from '@/app/components/workflow/types'
import {
RiAddLine,
} from '@remixicon/react'
import {
memo,
useCallback,
} from 'react'
import {
RiAddLine,
} from '@remixicon/react'
import { useTranslation } from 'react-i18next'
import BlockSelector from '@/app/components/workflow/block-selector'
import {
BlockEnum,
} from '@/app/components/workflow/types'
import { cn } from '@/utils/classnames'
import {
useAvailableBlocks,
useNodesInteractions,
useNodesReadOnly,
} from '../../hooks'
import type { LoopNodeType } from './types'
import { cn } from '@/utils/classnames'
import BlockSelector from '@/app/components/workflow/block-selector'
import type {
OnSelectBlock,
} from '@/app/components/workflow/types'
import {
BlockEnum,
} from '@/app/components/workflow/types'
type AddBlockProps = {
loopNodeId: string
@ -53,24 +53,25 @@ const AddBlock = ({
'system-sm-medium relative inline-flex h-8 cursor-pointer items-center rounded-lg border-[0.5px] border-components-button-secondary-border bg-components-button-secondary-bg px-3 text-components-button-secondary-text shadow-xs backdrop-blur-[5px] hover:bg-components-button-secondary-bg-hover',
`${nodesReadOnly && '!cursor-not-allowed bg-components-button-secondary-bg-disabled'}`,
open && 'bg-components-button-secondary-bg-hover',
)}>
<RiAddLine className='mr-1 h-4 w-4' />
)}
>
<RiAddLine className="mr-1 h-4 w-4" />
{t('workflow.common.addBlock')}
</div>
)
}, [nodesReadOnly, t])
return (
<div className='absolute left-14 top-7 z-10 flex h-8 items-center'>
<div className='group/insert relative h-0.5 w-16 bg-gray-300'>
<div className='absolute right-0 top-1/2 h-2 w-0.5 -translate-y-1/2 bg-primary-500'></div>
<div className="absolute left-14 top-7 z-10 flex h-8 items-center">
<div className="group/insert relative h-0.5 w-16 bg-gray-300">
<div className="absolute right-0 top-1/2 h-2 w-0.5 -translate-y-1/2 bg-primary-500"></div>
</div>
<BlockSelector
disabled={nodesReadOnly}
onSelect={handleSelect}
trigger={renderTriggerElement}
triggerInnerClassName='inline-flex'
popupClassName='!min-w-[256px]'
triggerInnerClassName="inline-flex"
popupClassName="!min-w-[256px]"
availableBlocksTypes={availableNextBlocks}
/>
</div>

View File

@ -1,10 +1,15 @@
import type { HandleAddCondition } from '../types'
import type {
NodeOutPutVar,
ValueSelector,
Var,
} from '@/app/components/workflow/types'
import { RiAddLine } from '@remixicon/react'
import {
useCallback,
useState,
} from 'react'
import { useTranslation } from 'react-i18next'
import { RiAddLine } from '@remixicon/react'
import type { HandleAddCondition } from '../types'
import Button from '@/app/components/base/button'
import {
PortalToFollowElem,
@ -12,11 +17,6 @@ import {
PortalToFollowElemTrigger,
} from '@/app/components/base/portal-to-follow-elem'
import VarReferenceVars from '@/app/components/workflow/nodes/_base/components/variable/var-reference-vars'
import type {
NodeOutPutVar,
ValueSelector,
Var,
} from '@/app/components/workflow/types'
type ConditionAddProps = {
className?: string
@ -42,7 +42,7 @@ const ConditionAdd = ({
<PortalToFollowElem
open={open}
onOpenChange={setOpen}
placement='bottom-start'
placement="bottom-start"
offset={{
mainAxis: 4,
crossAxis: 0,
@ -50,16 +50,16 @@ const ConditionAdd = ({
>
<PortalToFollowElemTrigger onClick={() => setOpen(!open)}>
<Button
size='small'
size="small"
className={className}
disabled={disabled}
>
<RiAddLine className='mr-1 h-3.5 w-3.5' />
<RiAddLine className="mr-1 h-3.5 w-3.5" />
{t('workflow.nodes.ifElse.addCondition')}
</Button>
</PortalToFollowElemTrigger>
<PortalToFollowElemContent className='z-[1000]'>
<div className='w-[296px] rounded-lg border-[0.5px] border-components-panel-border bg-components-panel-bg-blur shadow-lg'>
<PortalToFollowElemContent className="z-[1000]">
<div className="w-[296px] rounded-lg border-[0.5px] border-components-panel-border bg-components-panel-bg-blur shadow-lg">
<VarReferenceVars
vars={variables}
isSupportFileVar

View File

@ -1,20 +1,22 @@
import type { ValueSelector } from '../../../types'
import type { Condition } from '../types'
import {
memo,
useCallback,
} from 'react'
import { useTranslation } from 'react-i18next'
import { ComparisonOperator, type Condition } from '../types'
import { isSystemVar } from '@/app/components/workflow/nodes/_base/components/variable/utils'
import {
VariableLabelInNode,
} from '@/app/components/workflow/nodes/_base/components/variable/variable-label'
import { ComparisonOperator } from '../types'
import {
comparisonOperatorNotRequireValue,
isComparisonOperatorNeedTranslate,
isEmptyRelatedOperator,
} from '../utils'
import type { ValueSelector } from '../../../types'
import { FILE_TYPE_OPTIONS, TRANSFER_METHOD } from './../default'
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 = {
@ -39,7 +41,7 @@ const ConditionValue = ({
return ''
const value = c.value as string
return value.replace(/{{#([^#]*)#}}/g, (a, b) => {
return value.replace(/\{\{#([^#]*)#\}\}/g, (a, b) => {
const arr: string[] = b.split('.')
if (isSystemVar(arr))
return `{{${b}}}`
@ -57,41 +59,41 @@ const ConditionValue = ({
if (isSelect) {
const name = [...FILE_TYPE_OPTIONS, ...TRANSFER_METHOD].filter(item => item.value === (Array.isArray(c.value) ? c.value[0] : c.value))[0]
return name
? t(`workflow.nodes.ifElse.optionName.${name.i18nKey}`).replace(/{{#([^#]*)#}}/g, (a, b) => {
const arr: string[] = b.split('.')
if (isSystemVar(arr))
return `{{${b}}}`
? t(`workflow.nodes.ifElse.optionName.${name.i18nKey}`).replace(/\{\{#([^#]*)#\}\}/g, (a, b) => {
const arr: string[] = b.split('.')
if (isSystemVar(arr))
return `{{${b}}}`
return `{{${arr.slice(1).join('.')}}}`
})
return `{{${arr.slice(1).join('.')}}}`
})
: ''
}
return ''
}, [t])
return (
<div className='rounded-md bg-workflow-block-parma-bg'>
<div className='flex h-6 items-center px-1 '>
<div className="rounded-md bg-workflow-block-parma-bg">
<div className="flex h-6 items-center px-1 ">
<VariableLabelInNode
className='w-0 grow'
className="w-0 grow"
variables={variableSelector}
notShowFullPath
/>
<div
className='mx-1 shrink-0 text-xs font-medium text-text-primary'
className="mx-1 shrink-0 text-xs font-medium text-text-primary"
title={operatorName}
>
{operatorName}
</div>
</div>
<div className='ml-[10px] border-l border-divider-regular pl-[10px]'>
<div className="ml-[10px] border-l border-divider-regular pl-[10px]">
{
sub_variable_condition?.conditions.map((c: Condition, index) => (
<div className='relative flex h-6 items-center space-x-1' key={c.id}>
<div className='system-xs-medium text-text-accent'>{c.key}</div>
<div className='system-xs-medium text-text-primary'>{isComparisonOperatorNeedTranslate(c.comparison_operator) ? t(`workflow.nodes.ifElse.comparisonOperator.${c.comparison_operator}`) : c.comparison_operator}</div>
{c.comparison_operator && !isEmptyRelatedOperator(c.comparison_operator) && <div className='system-xs-regular text-text-secondary'>{isSelect(c) ? selectName(c) : formatValue(c)}</div>}
{index !== sub_variable_condition.conditions.length - 1 && (<div className='absolute bottom-[-10px] right-1 z-10 text-[10px] font-medium uppercase leading-4 text-text-accent'>{t(`${i18nPrefix}.${sub_variable_condition.logical_operator}`)}</div>)}
<div className="relative flex h-6 items-center space-x-1" key={c.id}>
<div className="system-xs-medium text-text-accent">{c.key}</div>
<div className="system-xs-medium text-text-primary">{isComparisonOperatorNeedTranslate(c.comparison_operator) ? t(`workflow.nodes.ifElse.comparisonOperator.${c.comparison_operator}`) : c.comparison_operator}</div>
{c.comparison_operator && !isEmptyRelatedOperator(c.comparison_operator) && <div className="system-xs-regular text-text-secondary">{isSelect(c) ? selectName(c) : formatValue(c)}</div>}
{index !== sub_variable_condition.conditions.length - 1 && (<div className="absolute bottom-[-10px] right-1 z-10 text-[10px] font-medium uppercase leading-4 text-text-accent">{t(`${i18nPrefix}.${sub_variable_condition.logical_operator}`)}</div>)}
</div>
))
}

View File

@ -1,10 +1,10 @@
import { useTranslation } from 'react-i18next'
import { useStore } from '@/app/components/workflow/store'
import PromptEditor from '@/app/components/base/prompt-editor'
import { BlockEnum } from '@/app/components/workflow/types'
import type {
Node,
} from '@/app/components/workflow/types'
import { useTranslation } from 'react-i18next'
import PromptEditor from '@/app/components/base/prompt-editor'
import { useStore } from '@/app/components/workflow/store'
import { BlockEnum } from '@/app/components/workflow/types'
type ConditionInputProps = {
disabled?: boolean

View File

@ -1,42 +1,42 @@
import {
useCallback,
useMemo,
useState,
} from 'react'
import { useTranslation } from 'react-i18next'
import { RiDeleteBinLine } from '@remixicon/react'
import { produce } from 'immer'
import type { VarType as NumberVarType } from '../../../tool/types'
import type {
Condition,
HandleAddSubVariableCondition,
HandleRemoveCondition,
handleRemoveSubVariableCondition,
HandleToggleSubVariableConditionLogicalOperator,
HandleUpdateCondition,
HandleUpdateSubVariableCondition,
handleRemoveSubVariableCondition,
} from '../../types'
import {
ComparisonOperator,
} from '../../types'
import ConditionNumberInput from '../condition-number-input'
import ConditionWrap from '../condition-wrap'
import { comparisonOperatorNotRequireValue, getOperators } from './../../utils'
import ConditionOperator from './condition-operator'
import ConditionInput from './condition-input'
import { FILE_TYPE_OPTIONS, SUB_VARIABLES, TRANSFER_METHOD } from './../../default'
import type {
Node,
NodeOutPutVar,
ValueSelector,
Var,
} from '@/app/components/workflow/types'
import { RiDeleteBinLine } from '@remixicon/react'
import { produce } from 'immer'
import {
useCallback,
useMemo,
useState,
} from 'react'
import { useTranslation } from 'react-i18next'
import { Variable02 } from '@/app/components/base/icons/src/vender/solid/development'
import { SimpleSelect as Select } from '@/app/components/base/select'
import BoolValue from '@/app/components/workflow/panel/chat-variable-panel/components/bool-value'
import { VarType } from '@/app/components/workflow/types'
import { cn } from '@/utils/classnames'
import { SimpleSelect as Select } from '@/app/components/base/select'
import { Variable02 } from '@/app/components/base/icons/src/vender/solid/development'
import {
ComparisonOperator,
} from '../../types'
import ConditionNumberInput from '../condition-number-input'
import ConditionWrap from '../condition-wrap'
import { FILE_TYPE_OPTIONS, SUB_VARIABLES, TRANSFER_METHOD } from './../../default'
import { comparisonOperatorNotRequireValue, getOperators } from './../../utils'
import ConditionInput from './condition-input'
import ConditionOperator from './condition-operator'
import ConditionVarSelector from './condition-var-selector'
import BoolValue from '@/app/components/workflow/panel/chat-variable-panel/components/bool-value'
const optionNameI18NPrefix = 'workflow.nodes.ifElse.optionName'
@ -209,45 +209,48 @@ const ConditionItem = ({
<div className={cn(
'grow rounded-lg bg-components-input-bg-normal',
isHovered && 'bg-state-destructive-hover',
)}>
<div className='flex items-center p-1'>
<div className='w-0 grow'>
)}
>
<div className="flex items-center p-1">
<div className="w-0 grow">
{isSubVarSelect
? (
<Select
wrapperClassName='h-6'
className='pl-0 text-xs'
optionWrapClassName='w-[165px] max-h-none'
defaultValue={condition.key}
items={subVarOptions}
onSelect={item => handleSubVarKeyChange(item.value as string)}
renderTrigger={item => (
item
? <div className='flex cursor-pointer justify-start'>
<div className='inline-flex h-6 max-w-full items-center rounded-md border-[0.5px] border-components-panel-border-subtle bg-components-badge-white-to-dark px-1.5 text-text-accent shadow-xs'>
<Variable02 className='h-3.5 w-3.5 shrink-0 text-text-accent' />
<div className='system-xs-medium ml-0.5 truncate'>{item?.name}</div>
</div>
</div>
: <div className='system-sm-regular text-left text-components-input-text-placeholder'>{t('common.placeholder.select')}</div>
)}
hideChecked
/>
)
<Select
wrapperClassName="h-6"
className="pl-0 text-xs"
optionWrapClassName="w-[165px] max-h-none"
defaultValue={condition.key}
items={subVarOptions}
onSelect={item => handleSubVarKeyChange(item.value as string)}
renderTrigger={item => (
item
? (
<div className="flex cursor-pointer justify-start">
<div className="inline-flex h-6 max-w-full items-center rounded-md border-[0.5px] border-components-panel-border-subtle bg-components-badge-white-to-dark px-1.5 text-text-accent shadow-xs">
<Variable02 className="h-3.5 w-3.5 shrink-0 text-text-accent" />
<div className="system-xs-medium ml-0.5 truncate">{item?.name}</div>
</div>
</div>
)
: <div className="system-sm-regular text-left text-components-input-text-placeholder">{t('common.placeholder.select')}</div>
)}
hideChecked
/>
)
: (
<ConditionVarSelector
open={open}
onOpenChange={setOpen}
valueSelector={condition.variable_selector || []}
varType={condition.varType}
availableNodes={availableNodes}
nodesOutputVars={availableVars}
onChange={handleVarChange}
/>
)}
<ConditionVarSelector
open={open}
onOpenChange={setOpen}
valueSelector={condition.variable_selector || []}
varType={condition.varType}
availableNodes={availableNodes}
nodesOutputVars={availableVars}
onChange={handleVarChange}
/>
)}
</div>
<div className='mx-1 h-3 w-[1px] bg-divider-regular'></div>
<div className="mx-1 h-3 w-[1px] bg-divider-regular"></div>
<ConditionOperator
disabled={!canChooseOperator}
varType={condition.varType}
@ -258,7 +261,7 @@ const ConditionItem = ({
</div>
{
!comparisonOperatorNotRequireValue(condition.comparison_operator) && !isNotInput && condition.varType !== VarType.number && condition.varType !== VarType.boolean && (
<div className='max-h-[100px] overflow-y-auto border-t border-t-divider-subtle px-2 py-1'>
<div className="max-h-[100px] overflow-y-auto border-t border-t-divider-subtle px-2 py-1">
<ConditionInput
disabled={disabled}
value={condition.value as string}
@ -269,16 +272,17 @@ const ConditionItem = ({
)
}
{!comparisonOperatorNotRequireValue(condition.comparison_operator) && condition.varType === VarType.boolean
&& <div className='p-1'>
<BoolValue
value={condition.value as boolean}
onChange={handleUpdateConditionValue}
/>
</div>
}
&& (
<div className="p-1">
<BoolValue
value={condition.value as boolean}
onChange={handleUpdateConditionValue}
/>
</div>
)}
{
!comparisonOperatorNotRequireValue(condition.comparison_operator) && !isNotInput && condition.varType === VarType.number && (
<div className='border-t border-t-divider-subtle px-2 py-1 pt-[3px]'>
<div className="border-t border-t-divider-subtle px-2 py-1 pt-[3px]">
<ConditionNumberInput
numberVarType={condition.numberVarType}
onNumberVarTypeChange={handleUpdateConditionNumberVarType}
@ -293,10 +297,10 @@ const ConditionItem = ({
}
{
!comparisonOperatorNotRequireValue(condition.comparison_operator) && isSelect && (
<div className='border-t border-t-divider-subtle'>
<div className="border-t border-t-divider-subtle">
<Select
wrapperClassName='h-8'
className='rounded-t-none px-2 text-xs'
wrapperClassName="h-8"
className="rounded-t-none px-2 text-xs"
defaultValue={isArrayValue ? (condition.value as string[])?.[0] : (condition.value as string)}
items={selectOptions}
onSelect={item => handleUpdateConditionValue(item.value as string)}
@ -308,7 +312,7 @@ const ConditionItem = ({
}
{
!comparisonOperatorNotRequireValue(condition.comparison_operator) && isSubVariable && (
<div className='p-1'>
<div className="p-1">
<ConditionWrap
isSubVariable
conditions={condition.sub_variable_condition?.conditions || []}
@ -328,12 +332,12 @@ const ConditionItem = ({
}
</div>
<div
className='ml-1 mt-1 flex h-6 w-6 shrink-0 cursor-pointer items-center justify-center rounded-lg text-text-tertiary hover:bg-state-destructive-hover hover:text-text-destructive'
className="ml-1 mt-1 flex h-6 w-6 shrink-0 cursor-pointer items-center justify-center rounded-lg text-text-tertiary hover:bg-state-destructive-hover hover:text-text-destructive"
onMouseEnter={() => setIsHovered(true)}
onMouseLeave={() => setIsHovered(false)}
onClick={doRemoveCondition}
>
<RiDeleteBinLine className='h-4 w-4' />
<RiDeleteBinLine className="h-4 w-4" />
</div>
</div>
)

View File

@ -1,19 +1,20 @@
import type { ComparisonOperator } from '../../types'
import type { VarType } from '@/app/components/workflow/types'
import { RiArrowDownSLine } from '@remixicon/react'
import {
useMemo,
useState,
} from 'react'
import { useTranslation } from 'react-i18next'
import { RiArrowDownSLine } from '@remixicon/react'
import { getOperators, isComparisonOperatorNeedTranslate } from '../../utils'
import type { ComparisonOperator } from '../../types'
import Button from '@/app/components/base/button'
import {
PortalToFollowElem,
PortalToFollowElemContent,
PortalToFollowElemTrigger,
} from '@/app/components/base/portal-to-follow-elem'
import type { VarType } from '@/app/components/workflow/types'
import { cn } from '@/utils/classnames'
import { getOperators, isComparisonOperatorNeedTranslate } from '../../utils'
const i18nPrefix = 'workflow.nodes.ifElse'
type ConditionOperatorProps = {
@ -48,7 +49,7 @@ const ConditionOperator = ({
<PortalToFollowElem
open={open}
onOpenChange={setOpen}
placement='bottom-end'
placement="bottom-end"
offset={{
mainAxis: 4,
crossAxis: 0,
@ -57,8 +58,8 @@ const ConditionOperator = ({
<PortalToFollowElemTrigger onClick={() => setOpen(v => !v)}>
<Button
className={cn('shrink-0', !selectedOption && 'opacity-50', className)}
size='small'
variant='ghost'
size="small"
variant="ghost"
disabled={disabled}
>
{
@ -66,16 +67,16 @@ const ConditionOperator = ({
? selectedOption.label
: t(`${i18nPrefix}.select`)
}
<RiArrowDownSLine className='ml-1 h-3.5 w-3.5' />
<RiArrowDownSLine className="ml-1 h-3.5 w-3.5" />
</Button>
</PortalToFollowElemTrigger>
<PortalToFollowElemContent className='z-10'>
<div className='rounded-xl border-[0.5px] border-components-panel-border bg-components-panel-bg-blur p-1 shadow-lg'>
<PortalToFollowElemContent className="z-10">
<div className="rounded-xl border-[0.5px] border-components-panel-border bg-components-panel-bg-blur p-1 shadow-lg">
{
options.map(option => (
<div
key={option.value}
className='flex h-7 cursor-pointer items-center rounded-lg px-3 py-1.5 text-[13px] font-medium text-text-secondary hover:bg-state-base-hover'
className="flex h-7 cursor-pointer items-center rounded-lg px-3 py-1.5 text-[13px] font-medium text-text-secondary hover:bg-state-base-hover"
onClick={() => {
onSelect(option.value)
setOpen(false)

View File

@ -1,7 +1,7 @@
import type { Node, NodeOutPutVar, ValueSelector, Var, VarType } from '@/app/components/workflow/types'
import { PortalToFollowElem, PortalToFollowElemContent, PortalToFollowElemTrigger } from '@/app/components/base/portal-to-follow-elem'
import VariableTag from '@/app/components/workflow/nodes/_base/components/variable-tag'
import VarReferenceVars from '@/app/components/workflow/nodes/_base/components/variable/var-reference-vars'
import type { Node, NodeOutPutVar, ValueSelector, Var, VarType } from '@/app/components/workflow/types'
type ConditionVarSelectorProps = {
open: boolean
@ -26,7 +26,7 @@ const ConditionVarSelector = ({
<PortalToFollowElem
open={open}
onOpenChange={onOpenChange}
placement='bottom-start'
placement="bottom-start"
offset={{
mainAxis: 4,
crossAxis: 0,
@ -42,8 +42,8 @@ const ConditionVarSelector = ({
/>
</div>
</PortalToFollowElemTrigger>
<PortalToFollowElemContent className='z-[1000]'>
<div className='w-[296px] rounded-lg border-[0.5px] border-components-panel-border bg-components-panel-bg-blur shadow-lg'>
<PortalToFollowElemContent className="z-[1000]">
<div className="w-[296px] rounded-lg border-[0.5px] border-components-panel-border bg-components-panel-bg-blur shadow-lg">
<VarReferenceVars
vars={nodesOutputVars}
isSupportFileVar

View File

@ -1,22 +1,17 @@
import { RiLoopLeftLine } from '@remixicon/react'
import { useCallback, useMemo } from 'react'
import {
type Condition,
type HandleAddSubVariableCondition,
type HandleRemoveCondition,
type HandleToggleConditionLogicalOperator,
type HandleToggleSubVariableConditionLogicalOperator,
type HandleUpdateCondition,
type HandleUpdateSubVariableCondition,
LogicalOperator,
type handleRemoveSubVariableCondition,
} from '../../types'
import ConditionItem from './condition-item'
import type { Condition, HandleAddSubVariableCondition, HandleRemoveCondition, handleRemoveSubVariableCondition, HandleToggleConditionLogicalOperator, HandleToggleSubVariableConditionLogicalOperator, HandleUpdateCondition, HandleUpdateSubVariableCondition } from '../../types'
import type {
Node,
NodeOutPutVar,
} from '@/app/components/workflow/types'
import { RiLoopLeftLine } from '@remixicon/react'
import { useCallback, useMemo } from 'react'
import { cn } from '@/utils/classnames'
import {
LogicalOperator,
} from '../../types'
import ConditionItem from './condition-item'
type ConditionListProps = {
isSubVariable?: boolean
@ -83,15 +78,16 @@ const ConditionList = ({
'absolute bottom-0 left-0 top-0 w-[60px]',
isSubVariable && logicalOperator === LogicalOperator.and && 'left-[-10px]',
isSubVariable && logicalOperator === LogicalOperator.or && 'left-[-18px]',
)}>
<div className='absolute bottom-4 left-[46px] top-4 w-2.5 rounded-l-[8px] border border-r-0 border-divider-deep'></div>
<div className='absolute right-0 top-1/2 h-[29px] w-4 -translate-y-1/2 bg-components-panel-bg'></div>
)}
>
<div className="absolute bottom-4 left-[46px] top-4 w-2.5 rounded-l-[8px] border border-r-0 border-divider-deep"></div>
<div className="absolute right-0 top-1/2 h-[29px] w-4 -translate-y-1/2 bg-components-panel-bg"></div>
<div
className='absolute right-1 top-1/2 flex h-[21px] -translate-y-1/2 cursor-pointer select-none items-center rounded-md border-[0.5px] border-components-button-secondary-border bg-components-button-secondary-bg px-1 text-[10px] font-semibold text-text-accent-secondary shadow-xs'
className="absolute right-1 top-1/2 flex h-[21px] -translate-y-1/2 cursor-pointer select-none items-center rounded-md border-[0.5px] border-components-button-secondary-border bg-components-button-secondary-bg px-1 text-[10px] font-semibold text-text-accent-secondary shadow-xs"
onClick={() => doToggleConditionLogicalOperator(conditionId)}
>
{logicalOperator && logicalOperator.toUpperCase()}
<RiLoopLeftLine className='ml-0.5 h-3 w-3' />
<RiLoopLeftLine className="ml-0.5 h-3 w-3" />
</div>
</div>
)

View File

@ -1,29 +1,29 @@
import type {
NodeOutPutVar,
ValueSelector,
} from '@/app/components/workflow/types'
import { RiArrowDownSLine } from '@remixicon/react'
import { useBoolean } from 'ahooks'
import { capitalize } from 'lodash-es'
import {
memo,
useCallback,
useState,
} from 'react'
import { useTranslation } from 'react-i18next'
import { RiArrowDownSLine } from '@remixicon/react'
import { capitalize } from 'lodash-es'
import { useBoolean } from 'ahooks'
import { VarType as NumberVarType } from '../../tool/types'
import VariableTag from '../../_base/components/variable-tag'
import Button from '@/app/components/base/button'
import { Variable02 } from '@/app/components/base/icons/src/vender/solid/development'
import {
PortalToFollowElem,
PortalToFollowElemContent,
PortalToFollowElemTrigger,
} from '@/app/components/base/portal-to-follow-elem'
import Button from '@/app/components/base/button'
import { cn } from '@/utils/classnames'
import VarReferenceVars from '@/app/components/workflow/nodes/_base/components/variable/var-reference-vars'
import type {
NodeOutPutVar,
ValueSelector,
} from '@/app/components/workflow/types'
import { VarType } from '@/app/components/workflow/types'
import { variableTransformer } from '@/app/components/workflow/utils'
import { Variable02 } from '@/app/components/base/icons/src/vender/solid/development'
import { cn } from '@/utils/classnames'
import VariableTag from '../../_base/components/variable-tag'
import { VarType as NumberVarType } from '../../tool/types'
const options = [
NumberVarType.variable,
@ -62,25 +62,25 @@ const ConditionNumberInput = ({
}, [onValueChange])
return (
<div className='flex cursor-pointer items-center'>
<div className="flex cursor-pointer items-center">
<PortalToFollowElem
open={numberVarTypeVisible}
onOpenChange={setNumberVarTypeVisible}
placement='bottom-start'
placement="bottom-start"
offset={{ mainAxis: 2, crossAxis: 0 }}
>
<PortalToFollowElemTrigger onClick={() => setNumberVarTypeVisible(v => !v)}>
<Button
className='shrink-0'
variant='ghost'
size='small'
className="shrink-0"
variant="ghost"
size="small"
>
{capitalize(numberVarType)}
<RiArrowDownSLine className='ml-[1px] h-3.5 w-3.5' />
<RiArrowDownSLine className="ml-[1px] h-3.5 w-3.5" />
</Button>
</PortalToFollowElemTrigger>
<PortalToFollowElemContent className='z-[1000]'>
<div className='w-[112px] rounded-xl border-[0.5px] border-components-panel-border bg-components-panel-bg-blur p-1 shadow-lg'>
<PortalToFollowElemContent className="z-[1000]">
<div className="w-[112px] rounded-xl border-[0.5px] border-components-panel-border bg-components-panel-bg-blur p-1 shadow-lg">
{
options.map(option => (
<div
@ -102,19 +102,20 @@ const ConditionNumberInput = ({
</div>
</PortalToFollowElemContent>
</PortalToFollowElem>
<div className='mx-1 h-4 w-[1px] bg-divider-regular'></div>
<div className='ml-0.5 w-0 grow'>
<div className="mx-1 h-4 w-[1px] bg-divider-regular"></div>
<div className="ml-0.5 w-0 grow">
{
numberVarType === NumberVarType.variable && (
<PortalToFollowElem
open={variableSelectorVisible}
onOpenChange={setVariableSelectorVisible}
placement='bottom-start'
placement="bottom-start"
offset={{ mainAxis: 2, crossAxis: 0 }}
>
<PortalToFollowElemTrigger
className='w-full'
onClick={() => setVariableSelectorVisible(v => !v)}>
className="w-full"
onClick={() => setVariableSelectorVisible(v => !v)}
>
{
value && (
<VariableTag
@ -126,14 +127,14 @@ const ConditionNumberInput = ({
}
{
!value && (
<div className='flex h-6 items-center p-1 text-[13px] text-components-input-text-placeholder'>
<Variable02 className='mr-1 h-4 w-4 shrink-0' />
<div className='w-0 grow truncate'>{t('workflow.nodes.ifElse.selectVariable')}</div>
<div className="flex h-6 items-center p-1 text-[13px] text-components-input-text-placeholder">
<Variable02 className="mr-1 h-4 w-4 shrink-0" />
<div className="w-0 grow truncate">{t('workflow.nodes.ifElse.selectVariable')}</div>
</div>
)
}
</PortalToFollowElemTrigger>
<PortalToFollowElemContent className='z-[1000]'>
<PortalToFollowElemContent className="z-[1000]">
<div className={cn('w-[296px] rounded-lg border-[0.5px] border-components-panel-border bg-components-panel-bg-blur pt-1 shadow-lg', isShort && 'w-[200px]')}>
<VarReferenceVars
vars={variables}
@ -146,17 +147,17 @@ const ConditionNumberInput = ({
}
{
numberVarType === NumberVarType.constant && (
<div className=' relative'>
<div className=" relative">
<input
className={cn('block w-full appearance-none bg-transparent px-2 text-[13px] text-components-input-text-filled outline-none placeholder:text-components-input-text-placeholder', unit && 'pr-6')}
type='number'
type="number"
value={value}
onChange={e => onValueChange(e.target.value)}
placeholder={t('workflow.nodes.ifElse.enterValue') || ''}
onFocus={setFocus}
onBlur={setBlur}
/>
{!isFocus && unit && <div className='system-sm-regular absolute right-2 top-[50%] translate-y-[-50%] text-text-tertiary'>{unit}</div>}
{!isFocus && unit && <div className="system-sm-regular absolute right-2 top-[50%] translate-y-[-50%] text-text-tertiary">{unit}</div>}
</div>
)
}

View File

@ -3,16 +3,16 @@ import {
useMemo,
} from 'react'
import { useTranslation } from 'react-i18next'
import { isSystemVar } from '@/app/components/workflow/nodes/_base/components/variable/utils'
import {
VariableLabelInNode,
} from '@/app/components/workflow/nodes/_base/components/variable/variable-label'
import { ComparisonOperator } from '../types'
import {
comparisonOperatorNotRequireValue,
isComparisonOperatorNeedTranslate,
} from '../utils'
import { FILE_TYPE_OPTIONS, TRANSFER_METHOD } from './../default'
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[]
@ -36,7 +36,7 @@ const ConditionValue = ({
if (Array.isArray(value)) // transfer method
return value[0]
return value.replace(/{{#([^#]*)#}}/g, (a, b) => {
return value.replace(/\{\{#([^#]*)#\}\}/g, (a, b) => {
const arr: string[] = b.split('.')
if (isSystemVar(arr))
return `{{${b}}}`
@ -50,34 +50,34 @@ const ConditionValue = ({
if (isSelect) {
const name = [...FILE_TYPE_OPTIONS, ...TRANSFER_METHOD].filter(item => item.value === (Array.isArray(value) ? value[0] : value))[0]
return name
? t(`workflow.nodes.ifElse.optionName.${name.i18nKey}`).replace(/{{#([^#]*)#}}/g, (a, b) => {
const arr: string[] = b.split('.')
if (isSystemVar(arr))
return `{{${b}}}`
? t(`workflow.nodes.ifElse.optionName.${name.i18nKey}`).replace(/\{\{#([^#]*)#\}\}/g, (a, b) => {
const arr: string[] = b.split('.')
if (isSystemVar(arr))
return `{{${b}}}`
return `{{${arr.slice(1).join('.')}}}`
})
return `{{${arr.slice(1).join('.')}}}`
})
: ''
}
return ''
}, [isSelect, t, value])
return (
<div className='flex h-6 items-center rounded-md bg-workflow-block-parma-bg px-1'>
<div className="flex h-6 items-center rounded-md bg-workflow-block-parma-bg px-1">
<VariableLabelInNode
className='w-0 grow'
className="w-0 grow"
variables={variableSelector}
notShowFullPath
/>
<div
className='mx-1 shrink-0 text-xs font-medium text-text-primary'
className="mx-1 shrink-0 text-xs font-medium text-text-primary"
title={operatorName}
>
{operatorName}
</div>
{
!notHasValue && (
<div className='truncate text-xs text-text-secondary' title={formatValue}>{isSelect ? selectName : formatValue}</div>
<div className="truncate text-xs text-text-secondary" title={formatValue}>{isSelect ? selectName : formatValue}</div>
)
}
</div>

View File

@ -1,20 +1,20 @@
'use client'
import type { FC } from 'react'
import React, { useCallback } from 'react'
import { useTranslation } from 'react-i18next'
import type { Node, NodeOutPutVar, Var } from '../../../types'
import type { Condition, HandleAddCondition, HandleAddSubVariableCondition, HandleRemoveCondition, handleRemoveSubVariableCondition, HandleToggleConditionLogicalOperator, HandleToggleSubVariableConditionLogicalOperator, HandleUpdateCondition, HandleUpdateSubVariableCondition, LogicalOperator } from '../types'
import {
RiAddLine,
} from '@remixicon/react'
import type { Condition, HandleAddCondition, HandleAddSubVariableCondition, HandleRemoveCondition, HandleToggleConditionLogicalOperator, HandleToggleSubVariableConditionLogicalOperator, HandleUpdateCondition, HandleUpdateSubVariableCondition, LogicalOperator, handleRemoveSubVariableCondition } from '../types'
import type { Node, NodeOutPutVar, Var } from '../../../types'
import { VarType } from '../../../types'
import { useGetAvailableVars } from '../../variable-assigner/hooks'
import ConditionList from './condition-list'
import ConditionAdd from './condition-add'
import { SUB_VARIABLES } from './../default'
import { cn } from '@/utils/classnames'
import React, { useCallback } from 'react'
import { useTranslation } from 'react-i18next'
import Button from '@/app/components/base/button'
import { PortalSelect as Select } from '@/app/components/base/select'
import { cn } from '@/utils/classnames'
import { VarType } from '../../../types'
import { useGetAvailableVars } from '../../variable-assigner/hooks'
import { SUB_VARIABLES } from './../default'
import ConditionAdd from './condition-add'
import ConditionList from './condition-list'
type Props = {
isSubVariable?: boolean
@ -81,7 +81,7 @@ const ConditionWrap: FC<Props> = ({
>
{
conditions && !!conditions.length && (
<div className='mb-2'>
<div className="mb-2">
<ConditionList
disabled={readOnly}
conditionId={conditionId}
@ -109,33 +109,34 @@ const ConditionWrap: FC<Props> = ({
!conditions.length && !isSubVariable && 'mt-1',
!conditions.length && isSubVariable && 'mt-2',
conditions.length > 1 && !isSubVariable && 'ml-[60px]',
)}>
)}
>
{isSubVariable
? (
<Select
popupInnerClassName='w-[165px] max-h-none'
onSelect={value => handleAddSubVariableCondition?.(conditionId!, value.value as string)}
items={subVarOptions}
value=''
renderTrigger={() => (
<Button
size='small'
disabled={readOnly}
>
<RiAddLine className='mr-1 h-3.5 w-3.5' />
{t('workflow.nodes.ifElse.addSubVariable')}
</Button>
)}
hideChecked
/>
)
<Select
popupInnerClassName="w-[165px] max-h-none"
onSelect={value => handleAddSubVariableCondition?.(conditionId!, value.value as string)}
items={subVarOptions}
value=""
renderTrigger={() => (
<Button
size="small"
disabled={readOnly}
>
<RiAddLine className="mr-1 h-3.5 w-3.5" />
{t('workflow.nodes.ifElse.addSubVariable')}
</Button>
)}
hideChecked
/>
)
: (
<ConditionAdd
disabled={readOnly}
variables={availableVars}
onSelectVariable={handleAddCondition!}
/>
)}
<ConditionAdd
disabled={readOnly}
variables={availableVars}
onSelectVariable={handleAddCondition!}
/>
)}
</div>
</div>
</div>

View File

@ -4,7 +4,7 @@ const Empty = () => {
const { t } = useTranslation()
return (
<div className='system-xs-regular flex h-10 items-center justify-center rounded-[10px] bg-background-section text-text-tertiary'>
<div className="system-xs-regular flex h-10 items-center justify-center rounded-[10px] bg-background-section text-text-tertiary">
{t('workflow.nodes.loop.setLoopVariables')}
</div>
)

View File

@ -1,13 +1,3 @@
import {
useCallback,
useMemo,
} from 'react'
import { useTranslation } from 'react-i18next'
import VarReferencePicker from '@/app/components/workflow/nodes/_base/components/variable/var-reference-picker'
import Input from '@/app/components/base/input'
import Textarea from '@/app/components/base/textarea'
import CodeEditor from '@/app/components/workflow/nodes/_base/components/editor/code-editor'
import { CodeLanguage } from '@/app/components/workflow/nodes/code/types'
import type {
LoopVariable,
} from '@/app/components/workflow/nodes/loop/types'
@ -15,9 +5,16 @@ import type {
Var,
} from '@/app/components/workflow/types'
import {
ValueType,
VarType,
} from '@/app/components/workflow/types'
useCallback,
useMemo,
} from 'react'
import { useTranslation } from 'react-i18next'
import Input from '@/app/components/base/input'
import Textarea from '@/app/components/base/textarea'
import CodeEditor from '@/app/components/workflow/nodes/_base/components/editor/code-editor'
import VarReferencePicker from '@/app/components/workflow/nodes/_base/components/variable/var-reference-picker'
import { CodeLanguage } from '@/app/components/workflow/nodes/code/types'
import ArrayBoolList from '@/app/components/workflow/panel/chat-variable-panel/components/array-bool-list'
import BoolValue from '@/app/components/workflow/panel/chat-variable-panel/components/bool-value'
import {
@ -27,7 +24,10 @@ import {
arrayStringPlaceholder,
objectPlaceholder,
} from '@/app/components/workflow/panel/chat-variable-panel/utils'
import ArrayBoolList from '@/app/components/workflow/panel/chat-variable-panel/components/array-bool-list'
import {
ValueType,
VarType,
} from '@/app/components/workflow/types'
type FormItemProps = {
nodeId: string
@ -91,7 +91,7 @@ const FormItem = ({
<Textarea
value={value}
onChange={handleInputChange}
className='min-h-12 w-full'
className="min-h-12 w-full"
/>
)
}
@ -101,7 +101,7 @@ const FormItem = ({
type="number"
value={value}
onChange={handleInputChange}
className='w-full'
className="w-full"
/>
)
}
@ -117,15 +117,15 @@ const FormItem = ({
value_type === ValueType.constant
&& (var_type === VarType.object || var_type === VarType.arrayString || var_type === VarType.arrayNumber || var_type === VarType.arrayObject)
&& (
<div className='w-full rounded-[10px] bg-components-input-bg-normal py-2 pl-3 pr-1' style={{ height: editorMinHeight }}>
<div className="w-full rounded-[10px] bg-components-input-bg-normal py-2 pl-3 pr-1" style={{ height: editorMinHeight }}>
<CodeEditor
value={value}
isExpand
noWrapper
language={CodeLanguage.json}
onChange={handleChange}
className='w-full'
placeholder={<div className='whitespace-pre'>{placeholder}</div>}
className="w-full"
placeholder={<div className="whitespace-pre">{placeholder}</div>}
/>
</div>
)
@ -133,7 +133,7 @@ const FormItem = ({
{
value_type === ValueType.constant && var_type === VarType.arrayBoolean && (
<ArrayBoolList
className='mt-2'
className="mt-2"
list={value || [false]}
onChange={handleChange}
/>

View File

@ -1,9 +1,9 @@
import Empty from './empty'
import Item from './item'
import type {
LoopVariable,
LoopVariablesComponentShape,
} from '@/app/components/workflow/nodes/loop/types'
import Empty from './empty'
import Item from './item'
type LoopVariableProps = {
variables?: LoopVariable[]

View File

@ -1,18 +1,18 @@
import { useCallback } from 'react'
import { RiDeleteBinLine } from '@remixicon/react'
import { useTranslation } from 'react-i18next'
import InputModeSelect from './input-mode-selec'
import VariableTypeSelect from './variable-type-select'
import FormItem from './form-item'
import ActionButton from '@/app/components/base/action-button'
import Input from '@/app/components/base/input'
import type {
LoopVariable,
LoopVariablesComponentShape,
} from '@/app/components/workflow/nodes/loop/types'
import { checkKeys, replaceSpaceWithUnderscoreInVarNameInput } from '@/utils/var'
import { RiDeleteBinLine } from '@remixicon/react'
import { useCallback } from 'react'
import { useTranslation } from 'react-i18next'
import ActionButton from '@/app/components/base/action-button'
import Input from '@/app/components/base/input'
import Toast from '@/app/components/base/toast'
import { ValueType, VarType } from '@/app/components/workflow/types'
import { checkKeys, replaceSpaceWithUnderscoreInVarNameInput } from '@/utils/var'
import FormItem from './form-item'
import InputModeSelect from './input-mode-selec'
import VariableTypeSelect from './variable-type-select'
type ItemProps = {
item: LoopVariable
@ -44,7 +44,7 @@ const Item = ({
}, [item.id, handleUpdateLoopVariable])
const getDefaultValue = useCallback((varType: VarType, valueType: ValueType) => {
if(valueType === ValueType.variable)
if (valueType === ValueType.variable)
return undefined
switch (varType) {
case VarType.boolean:
@ -69,9 +69,9 @@ const Item = ({
}, [item.id, handleUpdateLoopVariable])
return (
<div className='mb-4 flex last-of-type:mb-0'>
<div className='w-0 grow'>
<div className='mb-1 grid grid-cols-3 gap-1'>
<div className="mb-4 flex last-of-type:mb-0">
<div className="w-0 grow">
<div className="mb-1 grid grid-cols-3 gap-1">
<Input
value={item.label}
onChange={handleUpdateItemLabel}
@ -97,11 +97,11 @@ const Item = ({
</div>
</div>
<ActionButton
className='shrink-0'
size='l'
className="shrink-0"
size="l"
onClick={() => handleRemoveLoopVariable(item.id)}
>
<RiDeleteBinLine className='h-4 w-4 text-text-tertiary' />
<RiDeleteBinLine className="h-4 w-4 text-text-tertiary" />
</ActionButton>
</div>
)

View File

@ -1,12 +1,14 @@
import { VarType } from '../../types'
import type { NodeDefault } from '../../types'
import { ComparisonOperator, LogicalOperator, type LoopNodeType } from './types'
import { isEmptyRelatedOperator } from './utils'
import { TransferMethod } from '@/types/app'
import { LOOP_NODE_MAX_COUNT } from '@/config'
import { genNodeMetaData } from '@/app/components/workflow/utils'
import { BlockEnum } from '@/app/components/workflow/types'
import type { LoopNodeType } from './types'
import { BlockClassificationEnum } from '@/app/components/workflow/block-selector/types'
import { BlockEnum } from '@/app/components/workflow/types'
import { genNodeMetaData } from '@/app/components/workflow/utils'
import { LOOP_NODE_MAX_COUNT } from '@/config'
import { TransferMethod } from '@/types/app'
import { VarType } from '../../types'
import { ComparisonOperator, LogicalOperator } from './types'
import { isEmptyRelatedOperator } from './utils'
const i18nPrefix = 'workflow.errorMsg'
const metaData = genNodeMetaData({
@ -66,8 +68,9 @@ const nodeDefault: NodeDefault<LoopNodeType> = {
|| !Number.isInteger(Number(payload.loop_count))
|| payload.loop_count < 1
|| payload.loop_count > LOOP_NODE_MAX_COUNT
))
)) {
errorMessages = t('workflow.nodes.loop.loopMaxCountError', { maxCount: LOOP_NODE_MAX_COUNT })
}
return {
isValid: !errorMessages,

View File

@ -1,15 +1,15 @@
import type {
BlockEnum,
OnSelectBlock,
} from '../../types'
import {
memo,
useCallback,
useState,
} from 'react'
import { cn } from '@/utils/classnames'
import { useNodesInteractions } from '../../hooks'
import type {
BlockEnum,
OnSelectBlock,
} from '../../types'
import BlockSelector from '../../block-selector'
import { useNodesInteractions } from '../../hooks'
type InsertBlockProps = {
startNodeId: string

View File

@ -1,4 +1,6 @@
import type { FC } from 'react'
import type { LoopNodeType } from './types'
import type { NodeProps } from '@/app/components/workflow/types'
import {
memo,
useEffect,
@ -8,13 +10,11 @@ import {
useNodesInitialized,
useViewport,
} from 'reactflow'
import { LoopStartNodeDumb } from '../loop-start'
import { useNodeLoopInteractions } from './use-interactions'
import type { LoopNodeType } from './types'
import AddBlock from './add-block'
import { cn } from '@/utils/classnames'
import { LoopStartNodeDumb } from '../loop-start'
import AddBlock from './add-block'
import type { NodeProps } from '@/app/components/workflow/types'
import { useNodeLoopInteractions } from './use-interactions'
const Node: FC<NodeProps<LoopNodeType>> = ({
id,
@ -32,13 +32,14 @@ const Node: FC<NodeProps<LoopNodeType>> = ({
return (
<div className={cn(
'relative h-full min-h-[90px] w-full min-w-[240px] rounded-2xl bg-workflow-canvas-workflow-bg',
)}>
)}
>
<Background
id={`loop-background-${id}`}
className='!z-0 rounded-2xl'
className="!z-0 rounded-2xl"
gap={[14 / zoom, 14 / zoom]}
size={2 / zoom}
color='var(--color-workflow-canvas-workflow-dot-color)'
color="var(--color-workflow-canvas-workflow-dot-color)"
/>
{
data._isCandidate && (

View File

@ -1,17 +1,17 @@
import type { FC } from 'react'
import type { LoopNodeType } from './types'
import type { NodePanelProps } from '@/app/components/workflow/types'
import { RiAddLine } from '@remixicon/react'
import React from 'react'
import { useTranslation } from 'react-i18next'
import { RiAddLine } from '@remixicon/react'
import Split from '../_base/components/split'
import Field from '@/app/components/workflow/nodes/_base/components/field'
import { LOOP_NODE_MAX_COUNT } from '@/config'
import InputNumberWithSlider from '../_base/components/input-number-with-slider'
import type { LoopNodeType } from './types'
import useConfig from './use-config'
import Split from '../_base/components/split'
import ConditionWrap from './components/condition-wrap'
import LoopVariable from './components/loop-variables'
import type { NodePanelProps } from '@/app/components/workflow/types'
import Field from '@/app/components/workflow/nodes/_base/components/field'
import { LOOP_NODE_MAX_COUNT } from '@/config'
import useConfig from './use-config'
const i18nPrefix = 'workflow.nodes.loop'
@ -41,20 +41,20 @@ const Panel: FC<NodePanelProps<LoopNodeType>> = ({
} = useConfig(id, data)
return (
<div className='mt-2'>
<div className="mt-2">
<div>
<Field
title={<div className='pl-3'>{t('workflow.nodes.loop.loopVariables')}</div>}
operations={
title={<div className="pl-3">{t('workflow.nodes.loop.loopVariables')}</div>}
operations={(
<div
className='mr-4 flex h-5 w-5 cursor-pointer items-center justify-center'
className="mr-4 flex h-5 w-5 cursor-pointer items-center justify-center"
onClick={handleAddLoopVariable}
>
<RiAddLine className='h-4 w-4 text-text-tertiary' />
<RiAddLine className="h-4 w-4 text-text-tertiary" />
</div>
}
)}
>
<div className='px-4'>
<div className="px-4">
<LoopVariable
variables={inputs.loop_variables}
nodeId={id}
@ -63,9 +63,9 @@ const Panel: FC<NodePanelProps<LoopNodeType>> = ({
/>
</div>
</Field>
<Split className='my-2' />
<Split className="my-2" />
<Field
title={<div className='pl-3'>{t(`${i18nPrefix}.breakCondition`)}</div>}
title={<div className="pl-3">{t(`${i18nPrefix}.breakCondition`)}</div>}
tooltip={t(`${i18nPrefix}.breakConditionTip`)}
>
<ConditionWrap
@ -85,12 +85,12 @@ const Panel: FC<NodePanelProps<LoopNodeType>> = ({
logicalOperator={inputs.logical_operator!}
/>
</Field>
<Split className='mt-2' />
<div className='mt-2'>
<Split className="mt-2" />
<div className="mt-2">
<Field
title={<div className='pl-3'>{t(`${i18nPrefix}.loopMaxCount`)}</div>}
title={<div className="pl-3">{t(`${i18nPrefix}.loopMaxCount`)}</div>}
>
<div className='px-3 py-2'>
<div className="px-3 py-2">
<InputNumberWithSlider
min={1}
max={LOOP_NODE_MAX_COUNT}

View File

@ -1,20 +1,4 @@
import {
useCallback,
useRef,
} from 'react'
import { produce } from 'immer'
import { v4 as uuid4 } from 'uuid'
import {
useIsChatMode,
useNodesReadOnly,
useWorkflow,
} from '../../hooks'
import { ValueType, VarType } from '../../types'
import type { ErrorHandleMode, Var } from '../../types'
import useNodeCrud from '../_base/hooks/use-node-crud'
import { toNodeOutputVars } from '../_base/components/variable/utils'
import { getOperators } from './utils'
import { LogicalOperator } from './types'
import type {
HandleAddCondition,
HandleAddSubVariableCondition,
@ -25,7 +9,12 @@ import type {
HandleUpdateSubVariableCondition,
LoopNodeType,
} from './types'
import useIsVarFileAttribute from './use-is-var-file-attribute'
import { produce } from 'immer'
import {
useCallback,
useRef,
} from 'react'
import { v4 as uuid4 } from 'uuid'
import { useStore } from '@/app/components/workflow/store'
import {
useAllBuiltInTools,
@ -33,6 +22,17 @@ import {
useAllMCPTools,
useAllWorkflowTools,
} from '@/service/use-tools'
import {
useIsChatMode,
useNodesReadOnly,
useWorkflow,
} from '../../hooks'
import { ValueType, VarType } from '../../types'
import { toNodeOutputVars } from '../_base/components/variable/utils'
import useNodeCrud from '../_base/hooks/use-node-crud'
import { LogicalOperator } from './types'
import useIsVarFileAttribute from './use-is-var-file-attribute'
import { getOperators } from './utils'
const useConfig = (id: string, payload: LoopNodeType) => {
const { nodesReadOnly: readOnly } = useNodesReadOnly()

View File

@ -1,19 +1,19 @@
import { useCallback } from 'react'
import { produce } from 'immer'
import { useStoreApi } from 'reactflow'
import type {
BlockEnum,
Node,
} from '../../types'
import { produce } from 'immer'
import { useCallback } from 'react'
import { useStoreApi } from 'reactflow'
import { useNodesMetaData } from '@/app/components/workflow/hooks'
import {
LOOP_PADDING,
} from '../../constants'
import {
generateNewNode,
getNodeCustomTypeByNodeDataType,
} from '../../utils'
import {
LOOP_PADDING,
} from '../../constants'
import { CUSTOM_LOOP_START_NODE } from '../loop-start/constants'
import { useNodesMetaData } from '@/app/components/workflow/hooks'
export const useNodeLoopInteractions = () => {
const store = useStoreApi()
@ -75,7 +75,7 @@ export const useNodeLoopInteractions = () => {
const { getNodes } = store.getState()
const nodes = getNodes()
const restrictPosition: { x?: number; y?: number } = { x: undefined, y: undefined }
const restrictPosition: { x?: number, y?: number } = { x: undefined, y: undefined }
if (node.data.isInLoop) {
const parentNode = nodes.find(n => n.id === node.parentId)

View File

@ -1,6 +1,6 @@
import type { ValueSelector } from '../../types'
import { useMemo } from 'react'
import { useIsChatMode, useWorkflow, useWorkflowVariables } from '../../hooks'
import type { ValueSelector } from '../../types'
import { VarType } from '../../types'
type Params = {

View File

@ -1,13 +1,13 @@
import type { NodeTracing } from '@/types/workflow'
import { useCallback, useMemo } from 'react'
import formatTracing from '@/app/components/workflow/run/utils/format-log'
import { useTranslation } from 'react-i18next'
import { useIsNodeInLoop, useWorkflow } from '../../hooks'
import { getNodeInfoById, getNodeUsedVarPassToServerKey, getNodeUsedVars, isSystemVar } from '../_base/components/variable/utils'
import type { InputVar, ValueSelector, Variable } from '../../types'
import type { CaseItem, Condition, LoopNodeType } from './types'
import type { NodeTracing } from '@/types/workflow'
import { useCallback, useMemo } from 'react'
import { useTranslation } from 'react-i18next'
import formatTracing from '@/app/components/workflow/run/utils/format-log'
import { ValueType } from '@/app/components/workflow/types'
import { VALUE_SELECTOR_DELIMITER as DELIMITER } from '@/config'
import { useIsNodeInLoop, useWorkflow } from '../../hooks'
import { getNodeInfoById, getNodeUsedVarPassToServerKey, getNodeUsedVars, isSystemVar } from '../_base/components/variable/utils'
type Params = {
id: string

View File

@ -1,15 +1,18 @@
import { ComparisonOperator } from './types'
import { VarType } from '@/app/components/workflow/types'
import type { Branch } from '@/app/components/workflow/types'
import { VarType } from '@/app/components/workflow/types'
import { ComparisonOperator } from './types'
export const isEmptyRelatedOperator = (operator: ComparisonOperator) => {
return [ComparisonOperator.empty, ComparisonOperator.notEmpty, ComparisonOperator.isNull, ComparisonOperator.isNotNull, ComparisonOperator.exists, ComparisonOperator.notExists].includes(operator)
}
const notTranslateKey = [
ComparisonOperator.equal, ComparisonOperator.notEqual,
ComparisonOperator.largerThan, ComparisonOperator.largerThanOrEqual,
ComparisonOperator.lessThan, ComparisonOperator.lessThanOrEqual,
ComparisonOperator.equal,
ComparisonOperator.notEqual,
ComparisonOperator.largerThan,
ComparisonOperator.largerThanOrEqual,
ComparisonOperator.lessThan,
ComparisonOperator.lessThanOrEqual,
]
export const isComparisonOperatorNeedTranslate = (operator?: ComparisonOperator) => {