status.tsx 4.9 KB

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