segment-list.tsx 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120
  1. import React, { 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 = (
  27. {
  28. ref,
  29. isLoading,
  30. items,
  31. selectedSegmentIds,
  32. onSelected,
  33. onClick: onClickCard,
  34. onChangeSwitch,
  35. onDelete,
  36. onDeleteChildChunk,
  37. handleAddNewChildChunk,
  38. onClickSlice,
  39. archived,
  40. embeddingAvailable,
  41. onClearFilter,
  42. }: ISegmentListProps & {
  43. ref: React.RefObject<unknown>;
  44. },
  45. ) => {
  46. const mode = useDocumentContext(s => s.mode)
  47. const parentMode = useDocumentContext(s => s.parentMode)
  48. const currSegment = useSegmentListContext(s => s.currSegment)
  49. const currChildChunk = useSegmentListContext(s => s.currChildChunk)
  50. const Skeleton = useMemo(() => {
  51. return (mode === 'hierarchical' && parentMode === 'paragraph') ? ParagraphListSkeleton : GeneralListSkeleton
  52. }, [mode, parentMode])
  53. // Loading skeleton
  54. if (isLoading)
  55. return <Skeleton />
  56. // Search result is empty
  57. if (items.length === 0) {
  58. return (
  59. <div className='h-full pl-6'>
  60. <Empty onClearFilter={onClearFilter} />
  61. </div>
  62. )
  63. }
  64. return (
  65. <div ref={ref} className={'flex grow flex-col overflow-y-auto'}>
  66. {
  67. items.map((segItem) => {
  68. const isLast = items[items.length - 1].id === segItem.id
  69. const segmentIndexFocused
  70. = currSegment?.segInfo?.id === segItem.id
  71. || (!currSegment && currChildChunk?.childChunkInfo?.segment_id === segItem.id)
  72. const segmentContentFocused = currSegment?.segInfo?.id === segItem.id
  73. || currChildChunk?.childChunkInfo?.segment_id === segItem.id
  74. return (
  75. <div key={segItem.id} className='flex items-start gap-x-2'>
  76. <Checkbox
  77. key={`${segItem.id}-checkbox`}
  78. className='mt-3.5 shrink-0'
  79. checked={selectedSegmentIds.includes(segItem.id)}
  80. onCheck={() => onSelected(segItem.id)}
  81. />
  82. <div className='min-w-0 grow'>
  83. <SegmentCard
  84. key={`${segItem.id}-card`}
  85. detail={segItem}
  86. onClick={() => onClickCard(segItem, true)}
  87. onChangeSwitch={onChangeSwitch}
  88. onClickEdit={() => onClickCard(segItem, true)}
  89. onDelete={onDelete}
  90. onDeleteChildChunk={onDeleteChildChunk}
  91. handleAddNewChildChunk={handleAddNewChildChunk}
  92. onClickSlice={onClickSlice}
  93. loading={false}
  94. archived={archived}
  95. embeddingAvailable={embeddingAvailable}
  96. focused={{
  97. segmentIndex: segmentIndexFocused,
  98. segmentContent: segmentContentFocused,
  99. }}
  100. />
  101. {!isLast && <div className='w-full px-3'>
  102. <Divider type='horizontal' className='my-1 bg-divider-subtle' />
  103. </div>}
  104. </div>
  105. </div>
  106. )
  107. })
  108. }
  109. </div>
  110. )
  111. }
  112. SegmentList.displayName = 'SegmentList'
  113. export default SegmentList