You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

panel.tsx 5.0KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146
  1. import type { FC } from 'react'
  2. import React from 'react'
  3. import { useTranslation } from 'react-i18next'
  4. import { RiAddLine } from '@remixicon/react'
  5. import Split from '../_base/components/split'
  6. import ResultPanel from '../../run/result-panel'
  7. import InputNumberWithSlider from '../_base/components/input-number-with-slider'
  8. import type { LoopNodeType } from './types'
  9. import useConfig from './use-config'
  10. import ConditionWrap from './components/condition-wrap'
  11. import LoopVariable from './components/loop-variables'
  12. import type { NodePanelProps } from '@/app/components/workflow/types'
  13. import Field from '@/app/components/workflow/nodes/_base/components/field'
  14. import BeforeRunForm from '@/app/components/workflow/nodes/_base/components/before-run-form'
  15. import formatTracing from '@/app/components/workflow/run/utils/format-log'
  16. import { useLogs } from '@/app/components/workflow/run/hooks'
  17. import { LOOP_NODE_MAX_COUNT } from '@/config'
  18. const i18nPrefix = 'workflow.nodes.loop'
  19. const Panel: FC<NodePanelProps<LoopNodeType>> = ({
  20. id,
  21. data,
  22. }) => {
  23. const { t } = useTranslation()
  24. const {
  25. readOnly,
  26. inputs,
  27. childrenNodeVars,
  28. loopChildrenNodes,
  29. isShowSingleRun,
  30. hideSingleRun,
  31. runningStatus,
  32. handleRun,
  33. handleStop,
  34. runResult,
  35. loopRunResult,
  36. handleAddCondition,
  37. handleUpdateCondition,
  38. handleRemoveCondition,
  39. handleToggleConditionLogicalOperator,
  40. handleAddSubVariableCondition,
  41. handleRemoveSubVariableCondition,
  42. handleUpdateSubVariableCondition,
  43. handleToggleSubVariableConditionLogicalOperator,
  44. handleUpdateLoopCount,
  45. handleAddLoopVariable,
  46. handleRemoveLoopVariable,
  47. handleUpdateLoopVariable,
  48. } = useConfig(id, data)
  49. const nodeInfo = formatTracing(loopRunResult, t)[0]
  50. const logsParams = useLogs()
  51. return (
  52. <div className='mt-2'>
  53. <div>
  54. <Field
  55. title={<div className='pl-3'>{t('workflow.nodes.loop.loopVariables')}</div>}
  56. operations={
  57. <div
  58. className='mr-4 flex h-5 w-5 cursor-pointer items-center justify-center'
  59. onClick={handleAddLoopVariable}
  60. >
  61. <RiAddLine className='h-4 w-4 text-text-tertiary' />
  62. </div>
  63. }
  64. >
  65. <div className='px-4'>
  66. <LoopVariable
  67. variables={inputs.loop_variables}
  68. nodeId={id}
  69. handleRemoveLoopVariable={handleRemoveLoopVariable}
  70. handleUpdateLoopVariable={handleUpdateLoopVariable}
  71. />
  72. </div>
  73. </Field>
  74. <Split className='my-2' />
  75. <Field
  76. title={<div className='pl-3'>{t(`${i18nPrefix}.breakCondition`)}</div>}
  77. tooltip={t(`${i18nPrefix}.breakConditionTip`)}
  78. >
  79. <ConditionWrap
  80. nodeId={id}
  81. readOnly={readOnly}
  82. handleAddCondition={handleAddCondition}
  83. handleRemoveCondition={handleRemoveCondition}
  84. handleUpdateCondition={handleUpdateCondition}
  85. handleToggleConditionLogicalOperator={handleToggleConditionLogicalOperator}
  86. handleAddSubVariableCondition={handleAddSubVariableCondition}
  87. handleRemoveSubVariableCondition={handleRemoveSubVariableCondition}
  88. handleUpdateSubVariableCondition={handleUpdateSubVariableCondition}
  89. handleToggleSubVariableConditionLogicalOperator={handleToggleSubVariableConditionLogicalOperator}
  90. availableNodes={loopChildrenNodes}
  91. availableVars={childrenNodeVars}
  92. conditions={inputs.break_conditions || []}
  93. logicalOperator={inputs.logical_operator!}
  94. />
  95. </Field>
  96. <Split className='mt-2' />
  97. <div className='mt-2'>
  98. <Field
  99. title={<div className='pl-3'>{t(`${i18nPrefix}.loopMaxCount`)}</div>}
  100. >
  101. <div className='px-3 py-2'>
  102. <InputNumberWithSlider
  103. min={1}
  104. max={LOOP_NODE_MAX_COUNT}
  105. value={inputs.loop_count}
  106. onChange={(val) => {
  107. const roundedVal = Math.round(val)
  108. handleUpdateLoopCount(Number.isNaN(roundedVal) ? 1 : roundedVal)
  109. }}
  110. />
  111. </div>
  112. </Field>
  113. </div>
  114. </div>
  115. {/* Error handling for the Loop node is currently not considered. */}
  116. {/* <div className='px-4 py-2'>
  117. <Field title={t(`${i18nPrefix}.errorResponseMethod`)} >
  118. <Select items={responseMethod} defaultValue={inputs.error_handle_mode} onSelect={changeErrorResponseMode} allowSearch={false}>
  119. </Select>
  120. </Field>
  121. </div> */}
  122. {isShowSingleRun && (
  123. <BeforeRunForm
  124. nodeName={inputs.title}
  125. onHide={hideSingleRun}
  126. forms={[]}
  127. runningStatus={runningStatus}
  128. onRun={handleRun}
  129. onStop={handleStop}
  130. {...logsParams}
  131. result={
  132. <ResultPanel {...runResult} showSteps={false} nodeInfo={nodeInfo} {...logsParams} />
  133. }
  134. />
  135. )}
  136. </div>
  137. )
  138. }
  139. export default React.memo(Panel)