panel.tsx 6.6 KB

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