textarea.tsx 4.4 KB

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