mirror of https://github.com/langgenius/dify.git
feat: implement ChildSegmentList component and integrate it into SegmentCard for displaying child chunks
This commit is contained in:
parent
52ba180bf4
commit
b18eb58770
|
|
@ -0,0 +1,82 @@
|
|||
import { type FC, useState } from 'react'
|
||||
import { RiArrowDownSLine, RiArrowRightSLine } from '@remixicon/react'
|
||||
import { FormattedText } from '../../../formatted-text/formatted'
|
||||
import { EditSlice } from '../../../formatted-text/flavours/edit-slice'
|
||||
import { useDocumentContext } from '../index'
|
||||
import type { ChildChunkDetail } from '@/models/datasets'
|
||||
import Input from '@/app/components/base/input'
|
||||
import classNames from '@/utils/classnames'
|
||||
import Divider from '@/app/components/base/divider'
|
||||
|
||||
type IChildSegmentCardProps = {
|
||||
child_chunks: ChildChunkDetail[]
|
||||
onSave: () => void
|
||||
handleInputChange: (value: string) => void
|
||||
}
|
||||
|
||||
const ChildSegmentList: FC<IChildSegmentCardProps> = ({
|
||||
child_chunks,
|
||||
onSave,
|
||||
handleInputChange,
|
||||
}) => {
|
||||
let parentMode = useDocumentContext(s => s.parentMode)
|
||||
parentMode = 'paragraph'
|
||||
const [collapsed, setCollapsed] = useState(true)
|
||||
|
||||
const toggleCollapse = () => {
|
||||
setCollapsed(!collapsed)
|
||||
}
|
||||
|
||||
return (
|
||||
<div className='flex flex-col p-1 pb-2'>
|
||||
<div className='flex items-center justify-between'>
|
||||
<div className={classNames('h-7 flex items-center pl-1 pr-3 rounded-lg', collapsed ? 'bg-dataset-child-chunk-expand-btn-bg' : '')} onClick={(event) => {
|
||||
event.stopPropagation()
|
||||
toggleCollapse()
|
||||
}}>
|
||||
{
|
||||
parentMode === 'paragraph'
|
||||
? collapsed
|
||||
? (
|
||||
<RiArrowRightSLine className='w-4 h-4 text-text-secondary opacity-50 mr-0.5' />
|
||||
)
|
||||
: (<RiArrowDownSLine className='w-4 h-4 text-text-secondary mr-0.5' />)
|
||||
: null
|
||||
}
|
||||
<span className='text-text-secondary system-sm-semibold-uppercase'>{`${child_chunks.length} CHILD CHUNKS`}</span>
|
||||
<span className='hidden group-hover/card:inline-block text-text-quaternary text-xs font-medium pl-1.5'>·</span>
|
||||
<button className='hidden group-hover/card:inline-block px-1.5 py-1 text-components-button-secondary-accent-text system-xs-semibold'>ADD</button>
|
||||
</div>
|
||||
{parentMode === 'full-doc'
|
||||
? <Input
|
||||
showLeftIcon
|
||||
showClearIcon
|
||||
wrapperClassName='!w-52'
|
||||
value={''}
|
||||
onChange={e => handleInputChange(e.target.value)}
|
||||
onClear={() => handleInputChange('')}
|
||||
/>
|
||||
: null}
|
||||
</div>
|
||||
{(parentMode === 'full-doc' || !collapsed)
|
||||
? <div className='flex gap-x-0.5 p-1'>
|
||||
<Divider type='vertical' className='h-auto w-[2px] mx-[7px] bg-text-accent-secondary' />
|
||||
<FormattedText className='w-full !leading-5'>
|
||||
{child_chunks.map((childChunk, index) => {
|
||||
return <EditSlice
|
||||
key={index}
|
||||
label={`C-${childChunk.position}`}
|
||||
text={childChunk.content}
|
||||
onDelete={() => {}}
|
||||
className=''
|
||||
/>
|
||||
})}
|
||||
</FormattedText>
|
||||
</div>
|
||||
|
||||
: null}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
export default ChildSegmentList
|
||||
|
|
@ -11,6 +11,7 @@ import SegmentList from './segment-list'
|
|||
import DisplayToggle from './display-toggle'
|
||||
import BatchAction from './batch-action'
|
||||
import SegmentDetail from './segment-detail'
|
||||
import { mockSegments } from './mock-data'
|
||||
import cn from '@/utils/classnames'
|
||||
import { formatNumber } from '@/utils/format'
|
||||
import Modal from '@/app/components/base/modal'
|
||||
|
|
@ -123,8 +124,9 @@ const Completed: FC<ICompletedProps> = ({
|
|||
)
|
||||
|
||||
useEffect(() => {
|
||||
if (segmentList)
|
||||
setSegments(segmentList.data || [])
|
||||
setSegments(mockSegments.data)
|
||||
// if (segmentList)
|
||||
// setSegments(segmentList.data || [])
|
||||
}, [segmentList])
|
||||
|
||||
const resetList = useCallback(() => {
|
||||
|
|
|
|||
|
|
@ -1,3 +1,5 @@
|
|||
import type { ChildChunkType } from '@/models/datasets'
|
||||
|
||||
export const mockSegments = {
|
||||
data: [
|
||||
{
|
||||
|
|
@ -23,7 +25,7 @@ export const mockSegments = {
|
|||
index_node_id: 'b67972c2-4a95-4e46-bf8e-f32535bfc483',
|
||||
index_node_hash: '40ead185f2ec6a451da09e99f4f5a7438df4542590090660b7f2f40099220cf0',
|
||||
hit_count: 0,
|
||||
enabled: true,
|
||||
enabled: false,
|
||||
disabled_at: 1732081062,
|
||||
disabled_by: '',
|
||||
status: 'completed',
|
||||
|
|
@ -33,6 +35,26 @@ export const mockSegments = {
|
|||
completed_at: 1732081064,
|
||||
error: null,
|
||||
stopped_at: 1732081062,
|
||||
child_chunks: [
|
||||
{
|
||||
id: 'f3c7e7b6-5e7e-4c8d-9a0b-8f7e1c1f7a6d',
|
||||
position: 1,
|
||||
segment_id: '12aa196a-cf47-4962-a64a-7d927ed9b0ea',
|
||||
content: 'Dify 云服务 · 自托管 · 文档 · (需用英文)常见问题解答 / 联系团队\n\n',
|
||||
word_count: 45,
|
||||
created_at: 1732081062,
|
||||
type: 'automatic' as ChildChunkType,
|
||||
},
|
||||
{
|
||||
id: 'f3c7e7b6-5e7e-4c8d-9a0b-8f7e1c1f7a6c',
|
||||
position: 2,
|
||||
segment_id: '12aa196a-cf47-4962-a64a-7d927ed9b0ea',
|
||||
content: 'Dify 是一个开源的 LLM 应用开发平台。其直观的界面结合了 AI 工作流、RAG 管道、Agent、模型管理、可观测性功能等,让您可以快速从原型到生产。',
|
||||
word_count: 79,
|
||||
created_at: 1732081062,
|
||||
type: 'automatic' as ChildChunkType,
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
id: '4c701023-90a6-4df9-bc26-49cfb701badc',
|
||||
|
|
|
|||
|
|
@ -3,6 +3,8 @@ import { useTranslation } from 'react-i18next'
|
|||
import { RiArrowRightUpLine, RiDeleteBinLine, RiEditLine } from '@remixicon/react'
|
||||
import { StatusItem } from '../../list'
|
||||
import DocumentFileIcon from '../../../common/document-file-icon'
|
||||
import { useDocumentContext } from '../index'
|
||||
import ChildSegmentList from './child-segment-list'
|
||||
import { SegmentIndexTag, useSegmentListContext } from '.'
|
||||
import type { SegmentDetailModel } from '@/models/datasets'
|
||||
import Indicator from '@/app/components/header/indicator'
|
||||
|
|
@ -112,8 +114,11 @@ const SegmentCard: FC<ISegmentCardProps> = ({
|
|||
hit_count,
|
||||
answer,
|
||||
keywords,
|
||||
child_chunks = [],
|
||||
} = detail as Required<ISegmentCardProps>['detail']
|
||||
const [showModal, setShowModal] = useState(false)
|
||||
const isCollapsed = useSegmentListContext(s => s.isCollapsed)
|
||||
const mode = useDocumentContext(s => s.mode)
|
||||
|
||||
const isDocScene = useMemo(() => {
|
||||
return scene === 'doc'
|
||||
|
|
@ -149,11 +154,10 @@ const SegmentCard: FC<ISegmentCardProps> = ({
|
|||
|
||||
return content
|
||||
}
|
||||
const isCollapsed = useSegmentListContext(s => s.isCollapsed)
|
||||
|
||||
return (
|
||||
<div className={cn('p-3 pb-2.5 hover:bg-dataset-chunk-detail-card-hover-bg rounded-xl group/card', className)} onClick={() => onClick?.()}>
|
||||
<div className='relative flex items-center justify-between'>
|
||||
<div className={cn('p-1 pt-2.5 hover:bg-dataset-chunk-detail-card-hover-bg rounded-xl group/card', className, !enabled ? 'opacity-50 hover:opacity-100' : '')} onClick={() => onClick?.()}>
|
||||
<div className='h-5 px-2 relative flex items-center justify-between'>
|
||||
{isDocScene
|
||||
? <>
|
||||
<div className='flex items-center gap-x-2'>
|
||||
|
|
@ -167,7 +171,7 @@ const SegmentCard: FC<ISegmentCardProps> = ({
|
|||
<Badge text='edited' uppercase className={textOpacity} />
|
||||
)}
|
||||
</div>
|
||||
<div className=''>
|
||||
<div className='relative z-10'>
|
||||
{loading
|
||||
? (
|
||||
<Indicator color="gray" />
|
||||
|
|
@ -176,7 +180,7 @@ const SegmentCard: FC<ISegmentCardProps> = ({
|
|||
<>
|
||||
<StatusItem status={enabled ? 'enabled' : 'disabled'} reverse textCls="text-text-tertiary system-xs-regular" />
|
||||
{embeddingAvailable && (
|
||||
<div className="absolute -top-2.5 -right-2.5 z-20 hidden group-hover/card:flex items-center gap-x-0.5 p-1
|
||||
<div className="absolute -top-2 -right-2.5 z-20 hidden group-hover/card:flex items-center gap-x-0.5 p-1
|
||||
rounded-[10px] border-[0.5px] border-components-actionbar-border bg-components-actionbar-bg shadow-md backdrop-blur-[5px]">
|
||||
{!archived && (
|
||||
<>
|
||||
|
|
@ -240,12 +244,20 @@ const SegmentCard: FC<ISegmentCardProps> = ({
|
|||
: (
|
||||
isDocScene
|
||||
? <>
|
||||
<div className={cn('text-text-secondary body-md-regular -tracking-[0.07px] mt-1', textOpacity, isCollapsed ? 'line-clamp-2' : 'line-clamp-20')}>
|
||||
<div className={cn('text-text-secondary body-md-regular -tracking-[0.07px] mt-1 px-2', textOpacity, isCollapsed ? 'line-clamp-2' : 'line-clamp-20')}>
|
||||
{renderContent()}
|
||||
</div>
|
||||
<div className={cn('flex items-center gap-x-2 pt-1.5', textOpacity)}>
|
||||
{mode === 'custom' && <div className={cn('flex items-center gap-x-2 px-2 py-1.5', textOpacity)}>
|
||||
{keywords?.map(keyword => <Tag key={keyword} text={keyword} />)}
|
||||
</div>
|
||||
</div>}
|
||||
{
|
||||
child_chunks.length > 0
|
||||
&& <ChildSegmentList
|
||||
child_chunks={child_chunks}
|
||||
onSave={() => {}}
|
||||
handleInputChange={() => {}}
|
||||
/>
|
||||
}
|
||||
</>
|
||||
: <>
|
||||
<div className='text-text-secondary body-md-regular -tracking-[0.07px]'>
|
||||
|
|
|
|||
|
|
@ -100,6 +100,7 @@ module.exports = {
|
|||
'dataset-chunk-process-success-bg': 'var(--color-dataset-chunk-process-success-bg)',
|
||||
'dataset-chunk-process-error-bg': 'var(--color-dataset-chunk-process-error-bg)',
|
||||
'dataset-chunk-detail-card-hover-bg': 'var(--color-dataset-chunk-detail-card-hover-bg)',
|
||||
'dataset-child-chunk-expand-btn-bg': 'var(--color-dataset-child-chunk-expand-btn-bg)',
|
||||
},
|
||||
lineClamp: {
|
||||
20: '20',
|
||||
|
|
|
|||
|
|
@ -5,4 +5,5 @@ html[data-theme="dark"] {
|
|||
--color-dataset-chunk-process-success-bg: linear-gradient(92deg, rgba(23, 178, 106, 0.30) 0%, rgba(0, 0, 0, 0.00) 100%);
|
||||
--color-dataset-chunk-process-error-bg: linear-gradient(92deg, rgba(240, 68, 56, 0.30) 0%, rgba(0, 0, 0, 0.00) 100%);
|
||||
--color-dataset-chunk-detail-card-hover-bg: linear-gradient(180deg, #1D1D20 0%, #222225 100%);
|
||||
--color-dataset-child-chunk-expand-btn-bg: linear-gradient(90deg, rgba(24, 24, 27, 0.25) 0%, rgba(24, 24, 27, 0.04) 100%);
|
||||
}
|
||||
|
|
@ -5,4 +5,5 @@ html[data-theme="light"] {
|
|||
--color-dataset-chunk-process-success-bg: linear-gradient(92deg, rgba(23, 178, 106, 0.25) 0%, rgba(255, 255, 255, 0.00) 100%);
|
||||
--color-dataset-chunk-process-error-bg: linear-gradient(92deg, rgba(240, 68, 56, 0.25) 0%, rgba(255, 255, 255, 0.00) 100%);
|
||||
--color-dataset-chunk-detail-card-hover-bg: linear-gradient(180deg, #F2F4F7 0%, #F9FAFB 100%);
|
||||
--color-dataset-child-chunk-expand-btn-bg: linear-gradient(90deg, rgba(200, 206, 218, 0.20) 0%, rgba(200, 206, 218, 0.04) 100%);
|
||||
}
|
||||
Loading…
Reference in New Issue