Vous ne pouvez pas sélectionner plus de 25 sujets Les noms de sujets doivent commencer par une lettre ou un nombre, peuvent contenir des tirets ('-') et peuvent comporter jusqu'à 35 caractères.

index.tsx 4.5KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148
  1. import type {
  2. FC,
  3. } from 'react'
  4. import {
  5. memo,
  6. useMemo,
  7. } from 'react'
  8. import {
  9. RiAlertFill,
  10. RiCheckboxCircleFill,
  11. RiErrorWarningFill,
  12. RiLoader2Line,
  13. } from '@remixicon/react'
  14. import { useTranslation } from 'react-i18next'
  15. import {
  16. NodeTargetHandle,
  17. } from '@/app/components/workflow/nodes/_base/components/node-handle'
  18. import NodeControl from '@/app/components/workflow/nodes/_base/components/node-control'
  19. import cn from '@/utils/classnames'
  20. import BlockIcon from '@/app/components/workflow/block-icon'
  21. import type {
  22. NodeProps,
  23. } from '@/app/components/workflow/types'
  24. import {
  25. NodeRunningStatus,
  26. } from '@/app/components/workflow/types'
  27. import {
  28. useNodesReadOnly,
  29. } from '@/app/components/workflow/hooks'
  30. type SimpleNodeProps = NodeProps
  31. const SimpleNode: FC<SimpleNodeProps> = ({
  32. id,
  33. data,
  34. }) => {
  35. const { t } = useTranslation()
  36. const { nodesReadOnly } = useNodesReadOnly()
  37. const showSelectedBorder = data.selected || data._isBundled || data._isEntering
  38. const {
  39. showRunningBorder,
  40. showSuccessBorder,
  41. showFailedBorder,
  42. showExceptionBorder,
  43. } = useMemo(() => {
  44. return {
  45. showRunningBorder: data._runningStatus === NodeRunningStatus.Running && !showSelectedBorder,
  46. showSuccessBorder: data._runningStatus === NodeRunningStatus.Succeeded && !showSelectedBorder,
  47. showFailedBorder: data._runningStatus === NodeRunningStatus.Failed && !showSelectedBorder,
  48. showExceptionBorder: data._runningStatus === NodeRunningStatus.Exception && !showSelectedBorder,
  49. }
  50. }, [data._runningStatus, showSelectedBorder])
  51. return (
  52. <div
  53. className={cn(
  54. 'flex rounded-2xl border-[2px]',
  55. showSelectedBorder ? 'border-components-option-card-option-selected-border' : 'border-transparent',
  56. !showSelectedBorder && data._inParallelHovering && 'border-workflow-block-border-highlight',
  57. data._waitingRun && 'opacity-70',
  58. )}
  59. style={{
  60. width: 'auto',
  61. height: 'auto',
  62. }}
  63. >
  64. <div
  65. className={cn(
  66. 'group relative pb-1 shadow-xs',
  67. 'rounded-[15px] border border-transparent',
  68. 'w-[240px] bg-workflow-block-bg',
  69. !data._runningStatus && 'hover:shadow-lg',
  70. showRunningBorder && '!border-state-accent-solid',
  71. showSuccessBorder && '!border-state-success-solid',
  72. showFailedBorder && '!border-state-destructive-solid',
  73. showExceptionBorder && '!border-state-warning-solid',
  74. data._isBundled && '!shadow-lg',
  75. )}
  76. >
  77. {
  78. data._inParallelHovering && (
  79. <div className='top system-2xs-medium-uppercase absolute -top-2.5 left-2 z-10 text-text-tertiary'>
  80. {t('workflow.common.parallelRun')}
  81. </div>
  82. )
  83. }
  84. {
  85. !data._isCandidate && (
  86. <NodeTargetHandle
  87. id={id}
  88. data={data}
  89. handleClassName='!top-4 !-left-[9px] !translate-y-0'
  90. handleId='target'
  91. />
  92. )
  93. }
  94. {
  95. !data._runningStatus && !nodesReadOnly && !data._isCandidate && (
  96. <NodeControl
  97. id={id}
  98. data={data}
  99. />
  100. )
  101. }
  102. <div className={cn(
  103. 'flex items-center rounded-t-2xl px-3 pb-2 pt-3',
  104. )}>
  105. <BlockIcon
  106. className='mr-2 shrink-0'
  107. type={data.type}
  108. size='md'
  109. />
  110. <div
  111. title={data.title}
  112. className='system-sm-semibold-uppercase mr-1 flex grow items-center truncate text-text-primary'
  113. >
  114. <div>
  115. {data.title}
  116. </div>
  117. </div>
  118. {
  119. (data._runningStatus === NodeRunningStatus.Running || data._singleRunningStatus === NodeRunningStatus.Running) && (
  120. <RiLoader2Line className='h-3.5 w-3.5 animate-spin text-text-accent' />
  121. )
  122. }
  123. {
  124. data._runningStatus === NodeRunningStatus.Succeeded && (
  125. <RiCheckboxCircleFill className='h-3.5 w-3.5 text-text-success' />
  126. )
  127. }
  128. {
  129. data._runningStatus === NodeRunningStatus.Failed && (
  130. <RiErrorWarningFill className='h-3.5 w-3.5 text-text-destructive' />
  131. )
  132. }
  133. {
  134. data._runningStatus === NodeRunningStatus.Exception && (
  135. <RiAlertFill className='h-3.5 w-3.5 text-text-warning-secondary' />
  136. )
  137. }
  138. </div>
  139. </div>
  140. </div>
  141. )
  142. }
  143. export default memo(SimpleNode)