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.

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153
  1. 'use client'
  2. import type { FC } from 'react'
  3. import { useTranslation } from 'react-i18next'
  4. import cn from '@/utils/classnames'
  5. import Indicator from '@/app/components/header/indicator'
  6. import StatusContainer from '@/app/components/workflow/run/status-container'
  7. import { useDocLink } from '@/context/i18n'
  8. type ResultProps = {
  9. status: string
  10. time?: number
  11. tokens?: number
  12. error?: string
  13. exceptionCounts?: number
  14. }
  15. const StatusPanel: FC<ResultProps> = ({
  16. status,
  17. time,
  18. tokens,
  19. error,
  20. exceptionCounts,
  21. }) => {
  22. const { t } = useTranslation()
  23. const docLink = useDocLink()
  24. return (
  25. <StatusContainer status={status}>
  26. <div className='flex'>
  27. <div className={cn(
  28. 'max-w-[120px] flex-[33%]',
  29. status === 'partial-succeeded' && 'min-w-[140px]',
  30. )}>
  31. <div className='system-2xs-medium-uppercase mb-1 text-text-tertiary'>{t('runLog.resultPanel.status')}</div>
  32. <div
  33. className={cn(
  34. 'system-xs-semibold-uppercase flex items-center gap-1',
  35. status === 'succeeded' && 'text-util-colors-green-green-600',
  36. status === 'partial-succeeded' && 'text-util-colors-green-green-600',
  37. status === 'failed' && 'text-util-colors-red-red-600',
  38. status === 'stopped' && 'text-util-colors-warning-warning-600',
  39. status === 'running' && 'text-util-colors-blue-light-blue-light-600',
  40. )}
  41. >
  42. {status === 'running' && (
  43. <>
  44. <Indicator color={'blue'} />
  45. <span>Running</span>
  46. </>
  47. )}
  48. {status === 'succeeded' && (
  49. <>
  50. <Indicator color={'green'} />
  51. <span>SUCCESS</span>
  52. </>
  53. )}
  54. {status === 'partial-succeeded' && (
  55. <>
  56. <Indicator color={'green'} />
  57. <span>PARTIAL SUCCESS</span>
  58. </>
  59. )}
  60. {status === 'exception' && (
  61. <>
  62. <Indicator color={'yellow'} />
  63. <span>EXCEPTION</span>
  64. </>
  65. )}
  66. {status === 'failed' && (
  67. <>
  68. <Indicator color={'red'} />
  69. <span>FAIL</span>
  70. </>
  71. )}
  72. {status === 'stopped' && (
  73. <>
  74. <Indicator color={'yellow'} />
  75. <span>STOP</span>
  76. </>
  77. )}
  78. </div>
  79. </div>
  80. <div className='max-w-[152px] flex-[33%]'>
  81. <div className='system-2xs-medium-uppercase mb-1 text-text-tertiary'>{t('runLog.resultPanel.time')}</div>
  82. <div className='system-sm-medium flex items-center gap-1 text-text-secondary'>
  83. {status === 'running' && (
  84. <div className='h-2 w-16 rounded-sm bg-text-quaternary' />
  85. )}
  86. {status !== 'running' && (
  87. <span>{time ? `${time?.toFixed(3)}s` : '-'}</span>
  88. )}
  89. </div>
  90. </div>
  91. <div className='flex-[33%]'>
  92. <div className='system-2xs-medium-uppercase mb-1 text-text-tertiary'>{t('runLog.resultPanel.tokens')}</div>
  93. <div className='system-sm-medium flex items-center gap-1 text-text-secondary'>
  94. {status === 'running' && (
  95. <div className='h-2 w-20 rounded-sm bg-text-quaternary' />
  96. )}
  97. {status !== 'running' && (
  98. <span>{`${tokens || 0} Tokens`}</span>
  99. )}
  100. </div>
  101. </div>
  102. </div>
  103. {status === 'failed' && error && (
  104. <>
  105. <div className='my-2 h-[0.5px] bg-divider-subtle'/>
  106. <div className='system-xs-regular text-text-destructive'>{error}</div>
  107. {
  108. !!exceptionCounts && (
  109. <>
  110. <div className='my-2 h-[0.5px] bg-divider-subtle'/>
  111. <div className='system-xs-regular text-text-destructive'>
  112. {t('workflow.nodes.common.errorHandle.partialSucceeded.tip', { num: exceptionCounts })}
  113. </div>
  114. </>
  115. )
  116. }
  117. </>
  118. )}
  119. {
  120. status === 'partial-succeeded' && !!exceptionCounts && (
  121. <>
  122. <div className='my-2 h-[0.5px] bg-divider-deep'/>
  123. <div className='system-xs-medium text-text-warning'>
  124. {t('workflow.nodes.common.errorHandle.partialSucceeded.tip', { num: exceptionCounts })}
  125. </div>
  126. </>
  127. )
  128. }
  129. {
  130. status === 'exception' && (
  131. <>
  132. <div className='my-2 h-[0.5px] bg-divider-deep'/>
  133. <div className='system-xs-medium text-text-warning'>
  134. {error}
  135. <a
  136. href={docLink('/guides/workflow/error-handling/error-type')}
  137. target='_blank'
  138. className='text-text-accent'
  139. >
  140. {t('workflow.common.learnMore')}
  141. </a>
  142. </div>
  143. </>
  144. )
  145. }
  146. </StatusContainer>
  147. )
  148. }
  149. export default StatusPanel