textarea.tsx 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144
  1. import { useContext } from 'use-context-selector'
  2. import { useTranslation } from 'react-i18next'
  3. import cn from 'classnames'
  4. import Button from '../../base/button'
  5. import Tag from '../../base/tag'
  6. import Tooltip from '../../base/tooltip'
  7. import { getIcon } from '../common/retrieval-method-info'
  8. import s from './style.module.css'
  9. import DatasetDetailContext from '@/context/dataset-detail'
  10. import type { HitTestingResponse } from '@/models/datasets'
  11. import { hitTesting } from '@/service/datasets'
  12. import { asyncRunSafe } from '@/utils'
  13. import { RETRIEVE_METHOD, type RetrievalConfig } from '@/types/app'
  14. type TextAreaWithButtonIProps = {
  15. datasetId: string
  16. onUpdateList: () => void
  17. setHitResult: (res: HitTestingResponse) => void
  18. loading: boolean
  19. setLoading: (v: boolean) => void
  20. text: string
  21. setText: (v: string) => void
  22. onClickRetrievalMethod: () => void
  23. retrievalConfig: RetrievalConfig
  24. isEconomy: boolean
  25. onSubmit?: () => void
  26. }
  27. const TextAreaWithButton = ({
  28. datasetId,
  29. onUpdateList,
  30. setHitResult,
  31. setLoading,
  32. loading,
  33. text,
  34. setText,
  35. onClickRetrievalMethod,
  36. retrievalConfig,
  37. isEconomy,
  38. onSubmit: _onSubmit,
  39. }: TextAreaWithButtonIProps) => {
  40. const { t } = useTranslation()
  41. const { indexingTechnique } = useContext(DatasetDetailContext)
  42. function handleTextChange(event: any) {
  43. setText(event.target.value)
  44. }
  45. const onSubmit = async () => {
  46. setLoading(true)
  47. const [e, res] = await asyncRunSafe<HitTestingResponse>(
  48. hitTesting({ datasetId, queryText: text, retrieval_model: retrievalConfig }) as Promise<HitTestingResponse>,
  49. )
  50. if (!e) {
  51. setHitResult(res)
  52. onUpdateList?.()
  53. }
  54. setLoading(false)
  55. _onSubmit && _onSubmit()
  56. }
  57. const retrievalMethod = isEconomy ? RETRIEVE_METHOD.invertedIndex : retrievalConfig.search_method
  58. const Icon = getIcon(retrievalMethod)
  59. return (
  60. <>
  61. <div className={s.wrapper}>
  62. <div className='pt-2 rounded-tl-xl rounded-tr-xl bg-[#EEF4FF]'>
  63. <div className="px-4 pb-2 flex justify-between h-8 items-center">
  64. <span className="text-gray-800 font-semibold text-sm">
  65. {t('datasetHitTesting.input.title')}
  66. </span>
  67. <Tooltip
  68. selector={'change-retrieval-method'}
  69. htmlContent={t('dataset.retrieval.changeRetrievalMethod')}
  70. >
  71. <div
  72. onClick={onClickRetrievalMethod}
  73. className='flex px-2 h-7 items-center space-x-1 bg-white hover:bg-[#ECE9FE] rounded-md shadow-sm cursor-pointer text-[#6927DA]'
  74. >
  75. <Icon className='w-3.5 h-3.5'></Icon>
  76. <div className='text-xs font-medium'>{t(`dataset.retrieval.${retrievalMethod}.title`)}</div>
  77. </div>
  78. </Tooltip>
  79. </div>
  80. <div className='h-2 rounded-tl-xl rounded-tr-xl bg-white'></div>
  81. </div>
  82. <div className='px-4 pb-11'>
  83. <textarea
  84. value={text}
  85. onChange={handleTextChange}
  86. placeholder={t('datasetHitTesting.input.placeholder') as string}
  87. className={s.textarea}
  88. />
  89. <div className="absolute inset-x-0 bottom-0 flex items-center justify-between mx-4 mt-2 mb-2">
  90. {text?.length > 200
  91. ? (
  92. <Tooltip
  93. content={t('datasetHitTesting.input.countWarning') as string}
  94. selector="hit-testing-warning"
  95. >
  96. <div>
  97. <Tag color="red" className="!text-red-600">
  98. {text?.length}
  99. <span className="text-red-300 mx-0.5">/</span>
  100. 200
  101. </Tag>
  102. </div>
  103. </Tooltip>
  104. )
  105. : (
  106. <Tag
  107. color="gray"
  108. className={cn('!text-gray-500', text?.length ? '' : 'opacity-50')}
  109. >
  110. {text?.length}
  111. <span className="text-gray-300 mx-0.5">/</span>
  112. 200
  113. </Tag>
  114. )}
  115. <Tooltip
  116. selector="hit-testing-submit"
  117. disabled={indexingTechnique === 'high_quality'}
  118. content={t('datasetHitTesting.input.indexWarning') as string}
  119. >
  120. <div>
  121. <Button
  122. onClick={onSubmit}
  123. type="primary"
  124. loading={loading}
  125. disabled={indexingTechnique !== 'high_quality' ? true : (!text?.length || text?.length > 200)}
  126. >
  127. {t('datasetHitTesting.input.testing')}
  128. </Button>
  129. </div>
  130. </Tooltip>
  131. </div>
  132. </div>
  133. </div>
  134. </>
  135. )
  136. }
  137. export default TextAreaWithButton