chunk-detail-modal.tsx 3.5 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889
  1. 'use client'
  2. import type { FC } from 'react'
  3. import React from 'react'
  4. import { useTranslation } from 'react-i18next'
  5. import { SegmentIndexTag } from '../../documents/detail/completed/common/segment-index-tag'
  6. import Dot from '../../documents/detail/completed/common/dot'
  7. import Score from './score'
  8. import ChildChunksItem from './child-chunks-item'
  9. import Modal from '@/app/components/base/modal'
  10. import type { HitTesting } from '@/models/datasets'
  11. import FileIcon from '@/app/components/base/file-uploader/file-type-icon'
  12. import type { FileAppearanceTypeEnum } from '@/app/components/base/file-uploader/types'
  13. import cn from '@/utils/classnames'
  14. import Tag from '@/app/components/datasets/documents/detail/completed/common/tag'
  15. const i18nPrefix = 'datasetHitTesting'
  16. type Props = {
  17. payload: HitTesting
  18. onHide: () => void
  19. }
  20. const ChunkDetailModal: FC<Props> = ({
  21. payload,
  22. onHide,
  23. }) => {
  24. const { t } = useTranslation()
  25. const { segment, score, child_chunks } = payload
  26. const { position, content, keywords, document } = segment
  27. const isParentChildRetrieval = !!(child_chunks && child_chunks.length > 0)
  28. const extension = document.name.split('.').slice(-1)[0] as FileAppearanceTypeEnum
  29. const heighClassName = isParentChildRetrieval ? 'h-[min(627px,_80vh)] overflow-y-auto' : 'h-[min(539px,_80vh)] overflow-y-auto'
  30. return (
  31. <Modal
  32. title={t(`${i18nPrefix}.chunkDetail`)}
  33. isShow
  34. closable
  35. onClose={onHide}
  36. className={cn(isParentChildRetrieval ? '!min-w-[1200px]' : '!min-w-[800px]')}
  37. >
  38. <div className='mt-4 flex'>
  39. <div className={cn('flex-1', isParentChildRetrieval && 'pr-6')}>
  40. {/* Meta info */}
  41. <div className='flex justify-between items-center'>
  42. <div className='grow flex items-center space-x-2'>
  43. <SegmentIndexTag
  44. labelPrefix={`${isParentChildRetrieval ? 'Parent-' : ''}Chunk`}
  45. positionId={position}
  46. className={cn('w-fit group-hover:opacity-100')}
  47. />
  48. <Dot />
  49. <div className='grow flex items-center space-x-1'>
  50. <FileIcon type={extension} size='sm' />
  51. <span className='grow w-0 truncate text-text-secondary text-[13px] font-normal'>{document.name}</span>
  52. </div>
  53. </div>
  54. <Score value={score} />
  55. </div>
  56. <div className={cn('mt-2 body-md-regular text-text-secondary break-all', heighClassName)}>
  57. {content}
  58. </div>
  59. {!isParentChildRetrieval && keywords && keywords.length > 0 && (
  60. <div className='mt-6'>
  61. <div className='font-medium text-xs text-text-tertiary uppercase'>{t(`${i18nPrefix}.keyword`)}</div>
  62. <div className='mt-1 flex flex-wrap'>
  63. {keywords.map(keyword => (
  64. <Tag key={keyword} text={keyword} className='mr-2' />
  65. ))}
  66. </div>
  67. </div>
  68. )}
  69. </div>
  70. {isParentChildRetrieval && (
  71. <div className='flex-1 pl-6 pb-6'>
  72. <div className='system-xs-semibold-uppercase text-text-secondary'>{t(`${i18nPrefix}.hitChunks`, { num: child_chunks.length })}</div>
  73. <div className={cn('mt-1 space-y-2', heighClassName)}>
  74. {child_chunks.map(item => (
  75. <ChildChunksItem key={item.id} payload={item} isShowAll />
  76. ))}
  77. </div>
  78. </div>
  79. )}
  80. </div>
  81. </Modal>
  82. )
  83. }
  84. export default React.memo(ChunkDetailModal)