|
import type { FC } from 'react' |
|
import React from 'react' |
|
import { useTranslation } from 'react-i18next' |
|
import { |
|
RiArrowRightSLine, |
|
} from '@remixicon/react' |
|
import VarReferencePicker from '../_base/components/variable/var-reference-picker' |
|
import Split from '../_base/components/split' |
|
import ResultPanel from '../../run/result-panel' |
|
import IterationResultPanel from '../../run/iteration-result-panel' |
|
import { MAX_ITERATION_PARALLEL_NUM, MIN_ITERATION_PARALLEL_NUM } from '../../constants' |
|
import type { IterationNodeType } from './types' |
|
import useConfig from './use-config' |
|
import { ErrorHandleMode, InputVarType, type NodePanelProps } from '@/app/components/workflow/types' |
|
import Field from '@/app/components/workflow/nodes/_base/components/field' |
|
import BeforeRunForm from '@/app/components/workflow/nodes/_base/components/before-run-form' |
|
import Switch from '@/app/components/base/switch' |
|
import Select from '@/app/components/base/select' |
|
import Slider from '@/app/components/base/slider' |
|
import Input from '@/app/components/base/input' |
|
import Divider from '@/app/components/base/divider' |
|
|
|
const i18nPrefix = 'workflow.nodes.iteration' |
|
|
|
const Panel: FC<NodePanelProps<IterationNodeType>> = ({ |
|
id, |
|
data, |
|
}) => { |
|
const { t } = useTranslation() |
|
const responseMethod = [ |
|
{ |
|
value: ErrorHandleMode.Terminated, |
|
name: t(`${i18nPrefix}.ErrorMethod.operationTerminated`), |
|
}, |
|
{ |
|
value: ErrorHandleMode.ContinueOnError, |
|
name: t(`${i18nPrefix}.ErrorMethod.continueOnError`), |
|
}, |
|
{ |
|
value: ErrorHandleMode.RemoveAbnormalOutput, |
|
name: t(`${i18nPrefix}.ErrorMethod.removeAbnormalOutput`), |
|
}, |
|
] |
|
const { |
|
readOnly, |
|
inputs, |
|
filterInputVar, |
|
handleInputChange, |
|
childrenNodeVars, |
|
iterationChildrenNodes, |
|
handleOutputVarChange, |
|
isShowSingleRun, |
|
hideSingleRun, |
|
isShowIterationDetail, |
|
backToSingleRun, |
|
showIterationDetail, |
|
hideIterationDetail, |
|
runningStatus, |
|
handleRun, |
|
handleStop, |
|
runResult, |
|
inputVarValues, |
|
setInputVarValues, |
|
usedOutVars, |
|
iterator, |
|
setIterator, |
|
iteratorInputKey, |
|
iterationRunResult, |
|
changeParallel, |
|
changeErrorResponseMode, |
|
changeParallelNums, |
|
} = useConfig(id, data) |
|
|
|
return ( |
|
<div className='mt-2'> |
|
<div className='px-4 pb-4 space-y-4'> |
|
<Field |
|
title={t(`${i18nPrefix}.input`)} |
|
operations={( |
|
<div className='flex items-center h-[18px] px-1 border border-black/8 rounded-[5px] text-xs font-medium text-gray-500 capitalize'>Array</div> |
|
)} |
|
> |
|
<VarReferencePicker |
|
readonly={readOnly} |
|
nodeId={id} |
|
isShowNodeName |
|
value={inputs.iterator_selector || []} |
|
onChange={handleInputChange} |
|
filterVar={filterInputVar} |
|
/> |
|
</Field> |
|
</div> |
|
<Split /> |
|
<div className='mt-2 px-4 pb-4 space-y-4'> |
|
<Field |
|
title={t(`${i18nPrefix}.output`)} |
|
operations={( |
|
<div className='flex items-center h-[18px] px-1 border border-black/8 rounded-[5px] text-xs font-medium text-gray-500 capitalize'>Array</div> |
|
)} |
|
> |
|
<VarReferencePicker |
|
readonly={readOnly} |
|
nodeId={id} |
|
isShowNodeName |
|
value={inputs.output_selector || []} |
|
onChange={handleOutputVarChange} |
|
availableNodes={iterationChildrenNodes} |
|
availableVars={childrenNodeVars} |
|
/> |
|
</Field> |
|
</div> |
|
<div className='px-4 pb-2'> |
|
<Field title={t(`${i18nPrefix}.parallelMode`)} tooltip={<div className='w-[230px]'>{t(`${i18nPrefix}.parallelPanelDesc`)}</div>} inline> |
|
<Switch defaultValue={inputs.is_parallel} onChange={changeParallel} /> |
|
</Field> |
|
</div> |
|
{ |
|
inputs.is_parallel && (<div className='px-4 pb-2'> |
|
<Field title={t(`${i18nPrefix}.MaxParallelismTitle`)} isSubTitle tooltip={<div className='w-[230px]'>{t(`${i18nPrefix}.MaxParallelismDesc`)}</div>}> |
|
<div className='flex row'> |
|
<Input type='number' wrapperClassName='w-18 mr-4 ' max={MAX_ITERATION_PARALLEL_NUM} min={MIN_ITERATION_PARALLEL_NUM} value={inputs.parallel_nums} onChange={(e) => { changeParallelNums(Number(e.target.value)) }} /> |
|
<Slider |
|
value={inputs.parallel_nums} |
|
onChange={changeParallelNums} |
|
max={MAX_ITERATION_PARALLEL_NUM} |
|
min={MIN_ITERATION_PARALLEL_NUM} |
|
className=' flex-shrink-0 flex-1 mt-4' |
|
/> |
|
</div> |
|
|
|
</Field> |
|
</div>) |
|
} |
|
<div className='px-4 py-2'> |
|
<Divider className='h-[1px]'/> |
|
</div> |
|
|
|
<div className='px-4 py-2'> |
|
<Field title={t(`${i18nPrefix}.errorResponseMethod`)} > |
|
<Select items={responseMethod} defaultValue={inputs.error_handle_mode} onSelect={changeErrorResponseMode} allowSearch={false}> |
|
</Select> |
|
</Field> |
|
</div> |
|
|
|
{isShowSingleRun && ( |
|
<BeforeRunForm |
|
nodeName={inputs.title} |
|
onHide={hideSingleRun} |
|
forms={[ |
|
{ |
|
inputs: [...usedOutVars], |
|
values: inputVarValues, |
|
onChange: setInputVarValues, |
|
}, |
|
{ |
|
label: t(`${i18nPrefix}.input`)!, |
|
inputs: [{ |
|
label: '', |
|
variable: iteratorInputKey, |
|
type: InputVarType.iterator, |
|
required: false, |
|
}], |
|
values: { [iteratorInputKey]: iterator }, |
|
onChange: keyValue => setIterator((keyValue as any)[iteratorInputKey]), |
|
}, |
|
]} |
|
runningStatus={runningStatus} |
|
onRun={handleRun} |
|
onStop={handleStop} |
|
result={ |
|
<div className='mt-3'> |
|
<div className='px-4'> |
|
<div className='flex items-center h-[34px] justify-between px-3 bg-gray-100 border-[0.5px] border-gray-200 rounded-lg cursor-pointer' onClick={showIterationDetail}> |
|
<div className='leading-[18px] text-[13px] font-medium text-gray-700'>{t(`${i18nPrefix}.iteration`, { count: iterationRunResult.length })}</div> |
|
<RiArrowRightSLine className='w-3.5 h-3.5 text-gray-500' /> |
|
</div> |
|
<Split className='mt-3' /> |
|
</div> |
|
<ResultPanel {...runResult} showSteps={false} /> |
|
</div> |
|
} |
|
/> |
|
)} |
|
{isShowIterationDetail && ( |
|
<IterationResultPanel |
|
onBack={backToSingleRun} |
|
onHide={hideIterationDetail} |
|
list={iterationRunResult} |
|
/> |
|
)} |
|
</div> |
|
) |
|
} |
|
|
|
export default React.memo(Panel) |
|
|