segment-list.tsx 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117
  1. import React, { type ForwardedRef, useMemo } from 'react'
  2. import { useDocumentContext } from '../index'
  3. import SegmentCard from './segment-card'
  4. import Empty from './common/empty'
  5. import GeneralListSkeleton from './skeleton/general-list-skeleton'
  6. import ParagraphListSkeleton from './skeleton/paragraph-list-skeleton'
  7. import { useSegmentListContext } from './index'
  8. import type { ChildChunkDetail, SegmentDetailModel } from '@/models/datasets'
  9. import Checkbox from '@/app/components/base/checkbox'
  10. import Divider from '@/app/components/base/divider'
  11. type ISegmentListProps = {
  12. isLoading: boolean
  13. items: SegmentDetailModel[]
  14. selectedSegmentIds: string[]
  15. onSelected: (segId: string) => void
  16. onClick: (detail: SegmentDetailModel, isEditMode?: boolean) => void
  17. onChangeSwitch: (enabled: boolean, segId?: string,) => Promise<void>
  18. onDelete: (segId: string) => Promise<void>
  19. onDeleteChildChunk: (sgId: string, childChunkId: string) => Promise<void>
  20. handleAddNewChildChunk: (parentChunkId: string) => void
  21. onClickSlice: (childChunk: ChildChunkDetail) => void
  22. archived?: boolean
  23. embeddingAvailable: boolean
  24. onClearFilter: () => void
  25. }
  26. const SegmentList = React.forwardRef(({
  27. isLoading,
  28. items,
  29. selectedSegmentIds,
  30. onSelected,
  31. onClick: onClickCard,
  32. onChangeSwitch,
  33. onDelete,
  34. onDeleteChildChunk,
  35. handleAddNewChildChunk,
  36. onClickSlice,
  37. archived,
  38. embeddingAvailable,
  39. onClearFilter,
  40. }: ISegmentListProps,
  41. ref: ForwardedRef<HTMLDivElement>,
  42. ) => {
  43. const mode = useDocumentContext(s => s.mode)
  44. const parentMode = useDocumentContext(s => s.parentMode)
  45. const currSegment = useSegmentListContext(s => s.currSegment)
  46. const currChildChunk = useSegmentListContext(s => s.currChildChunk)
  47. const Skeleton = useMemo(() => {
  48. return (mode === 'hierarchical' && parentMode === 'paragraph') ? ParagraphListSkeleton : GeneralListSkeleton
  49. }, [mode, parentMode])
  50. // Loading skeleton
  51. if (isLoading)
  52. return <Skeleton />
  53. // Search result is empty
  54. if (items.length === 0) {
  55. return (
  56. <div className='h-full pl-6'>
  57. <Empty onClearFilter={onClearFilter} />
  58. </div>
  59. )
  60. }
  61. return (
  62. <div ref={ref} className={'flex flex-col grow overflow-y-auto'}>
  63. {
  64. items.map((segItem) => {
  65. const isLast = items[items.length - 1].id === segItem.id
  66. const segmentIndexFocused
  67. = currSegment?.segInfo?.id === segItem.id
  68. || (!currSegment && currChildChunk?.childChunkInfo?.segment_id === segItem.id)
  69. const segmentContentFocused = currSegment?.segInfo?.id === segItem.id
  70. || currChildChunk?.childChunkInfo?.segment_id === segItem.id
  71. return (
  72. <div key={segItem.id} className='flex items-start gap-x-2'>
  73. <Checkbox
  74. key={`${segItem.id}-checkbox`}
  75. className='shrink-0 mt-3.5'
  76. checked={selectedSegmentIds.includes(segItem.id)}
  77. onCheck={() => onSelected(segItem.id)}
  78. />
  79. <div className='grow min-w-0'>
  80. <SegmentCard
  81. key={`${segItem.id}-card`}
  82. detail={segItem}
  83. onClick={() => onClickCard(segItem, true)}
  84. onChangeSwitch={onChangeSwitch}
  85. onClickEdit={() => onClickCard(segItem, true)}
  86. onDelete={onDelete}
  87. onDeleteChildChunk={onDeleteChildChunk}
  88. handleAddNewChildChunk={handleAddNewChildChunk}
  89. onClickSlice={onClickSlice}
  90. loading={false}
  91. archived={archived}
  92. embeddingAvailable={embeddingAvailable}
  93. focused={{
  94. segmentIndex: segmentIndexFocused,
  95. segmentContent: segmentContentFocused,
  96. }}
  97. />
  98. {!isLast && <div className='w-full px-3'>
  99. <Divider type='horizontal' className='bg-divider-subtle my-1' />
  100. </div>}
  101. </div>
  102. </div>
  103. )
  104. })
  105. }
  106. </div>
  107. )
  108. })
  109. SegmentList.displayName = 'SegmentList'
  110. export default SegmentList