| 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) |
|
|