panel.tsx 6.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195
  1. import type { FC } from 'react'
  2. import React from 'react'
  3. import { useTranslation } from 'react-i18next'
  4. import {
  5. RiArrowRightSLine,
  6. } from '@remixicon/react'
  7. import VarReferencePicker from '../_base/components/variable/var-reference-picker'
  8. import Split from '../_base/components/split'
  9. import ResultPanel from '../../run/result-panel'
  10. import IterationResultPanel from '../../run/iteration-result-panel'
  11. import { MAX_ITERATION_PARALLEL_NUM, MIN_ITERATION_PARALLEL_NUM } from '../../constants'
  12. import type { IterationNodeType } from './types'
  13. import useConfig from './use-config'
  14. import { ErrorHandleMode, InputVarType, type NodePanelProps } from '@/app/components/workflow/types'
  15. import Field from '@/app/components/workflow/nodes/_base/components/field'
  16. import BeforeRunForm from '@/app/components/workflow/nodes/_base/components/before-run-form'
  17. import Switch from '@/app/components/base/switch'
  18. import Select from '@/app/components/base/select'
  19. import Slider from '@/app/components/base/slider'
  20. import Input from '@/app/components/base/input'
  21. import Divider from '@/app/components/base/divider'
  22. const i18nPrefix = 'workflow.nodes.iteration'
  23. const Panel: FC<NodePanelProps<IterationNodeType>> = ({
  24. id,
  25. data,
  26. }) => {
  27. const { t } = useTranslation()
  28. const responseMethod = [
  29. {
  30. value: ErrorHandleMode.Terminated,
  31. name: t(`${i18nPrefix}.ErrorMethod.operationTerminated`),
  32. },
  33. {
  34. value: ErrorHandleMode.ContinueOnError,
  35. name: t(`${i18nPrefix}.ErrorMethod.continueOnError`),
  36. },
  37. {
  38. value: ErrorHandleMode.RemoveAbnormalOutput,
  39. name: t(`${i18nPrefix}.ErrorMethod.removeAbnormalOutput`),
  40. },
  41. ]
  42. const {
  43. readOnly,
  44. inputs,
  45. filterInputVar,
  46. handleInputChange,
  47. childrenNodeVars,
  48. iterationChildrenNodes,
  49. handleOutputVarChange,
  50. isShowSingleRun,
  51. hideSingleRun,
  52. isShowIterationDetail,
  53. backToSingleRun,
  54. showIterationDetail,
  55. hideIterationDetail,
  56. runningStatus,
  57. handleRun,
  58. handleStop,
  59. runResult,
  60. inputVarValues,
  61. setInputVarValues,
  62. usedOutVars,
  63. iterator,
  64. setIterator,
  65. iteratorInputKey,
  66. iterationRunResult,
  67. changeParallel,
  68. changeErrorResponseMode,
  69. changeParallelNums,
  70. } = useConfig(id, data)
  71. return (
  72. <div className='mt-2'>
  73. <div className='px-4 pb-4 space-y-4'>
  74. <Field
  75. title={t(`${i18nPrefix}.input`)}
  76. operations={(
  77. <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>
  78. )}
  79. >
  80. <VarReferencePicker
  81. readonly={readOnly}
  82. nodeId={id}
  83. isShowNodeName
  84. value={inputs.iterator_selector || []}
  85. onChange={handleInputChange}
  86. filterVar={filterInputVar}
  87. />
  88. </Field>
  89. </div>
  90. <Split />
  91. <div className='mt-2 px-4 pb-4 space-y-4'>
  92. <Field
  93. title={t(`${i18nPrefix}.output`)}
  94. operations={(
  95. <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>
  96. )}
  97. >
  98. <VarReferencePicker
  99. readonly={readOnly}
  100. nodeId={id}
  101. isShowNodeName
  102. value={inputs.output_selector || []}
  103. onChange={handleOutputVarChange}
  104. availableNodes={iterationChildrenNodes}
  105. availableVars={childrenNodeVars}
  106. />
  107. </Field>
  108. </div>
  109. <div className='px-4 pb-2'>
  110. <Field title={t(`${i18nPrefix}.parallelMode`)} tooltip={<div className='w-[230px]'>{t(`${i18nPrefix}.parallelPanelDesc`)}</div>} inline>
  111. <Switch defaultValue={inputs.is_parallel} onChange={changeParallel} />
  112. </Field>
  113. </div>
  114. {
  115. inputs.is_parallel && (<div className='px-4 pb-2'>
  116. <Field title={t(`${i18nPrefix}.MaxParallelismTitle`)} isSubTitle tooltip={<div className='w-[230px]'>{t(`${i18nPrefix}.MaxParallelismDesc`)}</div>}>
  117. <div className='flex row'>
  118. <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)) }} />
  119. <Slider
  120. value={inputs.parallel_nums}
  121. onChange={changeParallelNums}
  122. max={MAX_ITERATION_PARALLEL_NUM}
  123. min={MIN_ITERATION_PARALLEL_NUM}
  124. className=' flex-shrink-0 flex-1 mt-4'
  125. />
  126. </div>
  127. </Field>
  128. </div>)
  129. }
  130. <div className='px-4 py-2'>
  131. <Divider className='h-[1px]'/>
  132. </div>
  133. <div className='px-4 py-2'>
  134. <Field title={t(`${i18nPrefix}.errorResponseMethod`)} >
  135. <Select items={responseMethod} defaultValue={inputs.error_handle_mode} onSelect={changeErrorResponseMode} allowSearch={false}>
  136. </Select>
  137. </Field>
  138. </div>
  139. {isShowSingleRun && (
  140. <BeforeRunForm
  141. nodeName={inputs.title}
  142. onHide={hideSingleRun}
  143. forms={[
  144. {
  145. inputs: [...usedOutVars],
  146. values: inputVarValues,
  147. onChange: setInputVarValues,
  148. },
  149. {
  150. label: t(`${i18nPrefix}.input`)!,
  151. inputs: [{
  152. label: '',
  153. variable: iteratorInputKey,
  154. type: InputVarType.iterator,
  155. required: false,
  156. }],
  157. values: { [iteratorInputKey]: iterator },
  158. onChange: keyValue => setIterator((keyValue as any)[iteratorInputKey]),
  159. },
  160. ]}
  161. runningStatus={runningStatus}
  162. onRun={handleRun}
  163. onStop={handleStop}
  164. result={
  165. <div className='mt-3'>
  166. <div className='px-4'>
  167. <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}>
  168. <div className='leading-[18px] text-[13px] font-medium text-gray-700'>{t(`${i18nPrefix}.iteration`, { count: iterationRunResult.length })}</div>
  169. <RiArrowRightSLine className='w-3.5 h-3.5 text-gray-500' />
  170. </div>
  171. <Split className='mt-3' />
  172. </div>
  173. <ResultPanel {...runResult} showSteps={false} />
  174. </div>
  175. }
  176. />
  177. )}
  178. {isShowIterationDetail && (
  179. <IterationResultPanel
  180. onBack={backToSingleRun}
  181. onHide={hideIterationDetail}
  182. list={iterationRunResult}
  183. />
  184. )}
  185. </div>
  186. )
  187. }
  188. export default React.memo(Panel)