mirror of https://github.com/langgenius/dify.git
feat: update child chunk handling and improve UI interactions
This commit is contained in:
parent
c1d1960215
commit
5a1159f9ab
|
|
@ -91,7 +91,7 @@ const ChildSegmentList: FC<IChildSegmentCardProps> = ({
|
|||
{isParagraphMode && <Divider type='vertical' className='h-auto w-[2px] mx-[7px] bg-text-accent-secondary' />}
|
||||
<div className={classNames('w-full !leading-5 flex flex-col', isParagraphMode ? 'gap-y-2' : 'gap-y-3')}>
|
||||
{childChunks.map((childChunk) => {
|
||||
const edited = childChunk.type === 'customized'
|
||||
const edited = childChunk.updated_at !== childChunk.created_at
|
||||
return <EditSlice
|
||||
key={childChunk.id}
|
||||
label={`C-${childChunk.position}${edited ? '·EDITED' : ''}`}
|
||||
|
|
|
|||
|
|
@ -229,7 +229,7 @@ const Completed: FC<ICompletedProps> = ({
|
|||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, [datasetId, documentId, selectedSegmentIds])
|
||||
|
||||
const handleUpdateSegment = async (
|
||||
const handleUpdateSegment = useCallback(async (
|
||||
segmentId: string,
|
||||
question: string,
|
||||
answer: string,
|
||||
|
|
@ -283,7 +283,8 @@ const Completed: FC<ICompletedProps> = ({
|
|||
finally {
|
||||
eventEmitter?.emit('update-segment-done')
|
||||
}
|
||||
}
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, [segments, datasetId, documentId])
|
||||
|
||||
useEffect(() => {
|
||||
if (importStatus === ProcessStatus.COMPLETED)
|
||||
|
|
@ -360,13 +361,27 @@ const Completed: FC<ICompletedProps> = ({
|
|||
},
|
||||
)
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, [datasetId, documentId])
|
||||
}, [datasetId, documentId, parentMode])
|
||||
|
||||
const handleAddNewChildChunk = useCallback((parentChunkId: string) => {
|
||||
setShowNewChildSegmentModal(true)
|
||||
setCurrChunkId(parentChunkId)
|
||||
}, [])
|
||||
|
||||
const onSaveNewChildChunk = useCallback((newChildChunk?: ChildChunkDetail) => {
|
||||
if (parentMode === 'paragraph') {
|
||||
for (const seg of segments) {
|
||||
if (seg.id === currChunkId)
|
||||
seg.child_chunks?.push(newChildChunk!)
|
||||
}
|
||||
setSegments([...segments])
|
||||
}
|
||||
else {
|
||||
resetChildList()
|
||||
}
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, [parentMode, currChunkId, segments])
|
||||
|
||||
const viewNewlyAddedChildChunk = useCallback(() => {
|
||||
const totalPages = childChunkListData?.total_pages || 0
|
||||
const total = childChunkListData?.total || 0
|
||||
|
|
@ -394,7 +409,7 @@ const Completed: FC<ICompletedProps> = ({
|
|||
|
||||
const { mutateAsync: updateChildSegment } = useUpdateChildSegment()
|
||||
|
||||
const handleUpdateChildChunk = async (
|
||||
const handleUpdateChildChunk = useCallback(async (
|
||||
segmentId: string,
|
||||
childChunkId: string,
|
||||
content: string,
|
||||
|
|
@ -418,6 +433,7 @@ const Completed: FC<ICompletedProps> = ({
|
|||
childSeg.content = res.data.content
|
||||
childSeg.type = res.data.type
|
||||
childSeg.word_count = res.data.word_count
|
||||
childSeg.updated_at = res.data.updated_at
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -430,6 +446,7 @@ const Completed: FC<ICompletedProps> = ({
|
|||
childSeg.content = res.data.content
|
||||
childSeg.type = res.data.type
|
||||
childSeg.word_count = res.data.word_count
|
||||
childSeg.updated_at = res.data.updated_at
|
||||
}
|
||||
}
|
||||
setChildSegments([...childSegments])
|
||||
|
|
@ -438,7 +455,8 @@ const Completed: FC<ICompletedProps> = ({
|
|||
finally {
|
||||
eventEmitter?.emit('update-child-segment-done')
|
||||
}
|
||||
}
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, [segments, childSegments, datasetId, documentId, parentMode])
|
||||
|
||||
return (
|
||||
<SegmentListContext.Provider value={{
|
||||
|
|
@ -571,12 +589,7 @@ const Completed: FC<ICompletedProps> = ({
|
|||
setShowNewChildSegmentModal(false)
|
||||
setFullScreen(false)
|
||||
}}
|
||||
onSave={() => {
|
||||
if (parentMode === 'paragraph')
|
||||
resetList()
|
||||
else
|
||||
resetChildList()
|
||||
}}
|
||||
onSave={onSaveNewChildChunk}
|
||||
viewNewlyAddedChildChunk={viewNewlyAddedChildChunk}
|
||||
/>
|
||||
</FullScreenDrawer>
|
||||
|
|
|
|||
|
|
@ -1,10 +1,11 @@
|
|||
import { memo, useRef, useState } from 'react'
|
||||
import { memo, useMemo, useRef, useState } from 'react'
|
||||
import type { FC } from 'react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import { useContext } from 'use-context-selector'
|
||||
import { useParams } from 'next/navigation'
|
||||
import { RiCloseLine, RiExpandDiagonalLine } from '@remixicon/react'
|
||||
import { useShallow } from 'zustand/react/shallow'
|
||||
import { useDocumentContext } from '../index'
|
||||
import { SegmentIndexTag } from './common/segment-index-tag'
|
||||
import ActionButtons from './common/action-buttons'
|
||||
import ChunkContent from './common/chunk-content'
|
||||
|
|
@ -13,7 +14,7 @@ import Dot from './common/dot'
|
|||
import { useSegmentListContext } from './index'
|
||||
import { useStore as useAppStore } from '@/app/components/app/store'
|
||||
import { ToastContext } from '@/app/components/base/toast'
|
||||
import type { SegmentUpdater } from '@/models/datasets'
|
||||
import type { ChildChunkDetail, SegmentUpdater } from '@/models/datasets'
|
||||
import classNames from '@/utils/classnames'
|
||||
import { formatNumber } from '@/utils/format'
|
||||
import Divider from '@/app/components/base/divider'
|
||||
|
|
@ -22,7 +23,7 @@ import { useAddChildSegment } from '@/service/knowledge/use-segment'
|
|||
type NewChildSegmentModalProps = {
|
||||
chunkId: string
|
||||
onCancel: () => void
|
||||
onSave: () => void
|
||||
onSave: (ChildChunk?: ChildChunkDetail) => void
|
||||
viewNewlyAddedChildChunk?: () => void
|
||||
}
|
||||
|
||||
|
|
@ -42,15 +43,21 @@ const NewChildSegmentModal: FC<NewChildSegmentModalProps> = ({
|
|||
const { appSidebarExpand } = useAppStore(useShallow(state => ({
|
||||
appSidebarExpand: state.appSidebarExpand,
|
||||
})))
|
||||
const parentMode = useDocumentContext(s => s.parentMode)
|
||||
|
||||
const refreshTimer = useRef<any>(null)
|
||||
|
||||
const isFullDocMode = useMemo(() => {
|
||||
return parentMode === 'full-doc'
|
||||
}, [parentMode])
|
||||
|
||||
const CustomButton = <>
|
||||
<Divider type='vertical' className='h-3 mx-1 bg-divider-regular' />
|
||||
<button className='text-text-accent system-xs-semibold' onClick={() => {
|
||||
clearTimeout(refreshTimer.current)
|
||||
viewNewlyAddedChildChunk?.()
|
||||
}}>
|
||||
{t('datasetDocuments.segment.viewAddedChunk')}
|
||||
{t('common.operation.view')}
|
||||
</button>
|
||||
</>
|
||||
|
||||
|
|
@ -72,18 +79,23 @@ const NewChildSegmentModal: FC<NewChildSegmentModalProps> = ({
|
|||
|
||||
setLoading(true)
|
||||
try {
|
||||
await addChildSegment({ datasetId, documentId, segmentId: chunkId, body: params })
|
||||
const res = await addChildSegment({ datasetId, documentId, segmentId: chunkId, body: params })
|
||||
notify({
|
||||
type: 'success',
|
||||
message: t('datasetDocuments.segment.chunkAdded'),
|
||||
message: t('datasetDocuments.segment.childChunkAdded'),
|
||||
className: `!w-[296px] !bottom-0 ${appSidebarExpand === 'expand' ? '!left-[216px]' : '!left-14'}
|
||||
!top-auto !right-auto !mb-[52px] !ml-11`,
|
||||
customComponent: CustomButton,
|
||||
customComponent: isFullDocMode && CustomButton,
|
||||
})
|
||||
handleCancel('add')
|
||||
refreshTimer.current = setTimeout(() => {
|
||||
onSave()
|
||||
}, 3000)
|
||||
if (isFullDocMode) {
|
||||
refreshTimer.current = setTimeout(() => {
|
||||
onSave()
|
||||
}, 3000)
|
||||
}
|
||||
else {
|
||||
onSave(res.data)
|
||||
}
|
||||
}
|
||||
finally {
|
||||
setLoading(false)
|
||||
|
|
|
|||
|
|
@ -55,7 +55,7 @@ const NewSegmentModal: FC<NewSegmentModalProps> = ({
|
|||
clearTimeout(refreshTimer.current)
|
||||
viewNewlyAddedChunk()
|
||||
}}>
|
||||
{t('datasetDocuments.segment.viewAddedChunk')}
|
||||
{t('common.operation.view')}
|
||||
</button>
|
||||
</>
|
||||
|
||||
|
|
|
|||
|
|
@ -44,6 +44,7 @@ const translation = {
|
|||
openInNewTab: 'Open in new tab',
|
||||
saveAndRegenerate: 'Save & Regenerate Child Chunks',
|
||||
close: 'Close',
|
||||
view: 'View',
|
||||
viewMore: 'VIEW MORE',
|
||||
regenerate: 'Regenerate',
|
||||
},
|
||||
|
|
|
|||
|
|
@ -353,7 +353,7 @@ const translation = {
|
|||
addAnother: 'Add another',
|
||||
delete: 'Delete this chunk ?',
|
||||
chunkAdded: '1 chunk added',
|
||||
viewAddedChunk: 'View',
|
||||
childChunkAdded: '1 child chunk added',
|
||||
regenerationConfirmTitle: 'Do you want to regenerate child chunks?',
|
||||
regenerationConfirmMessage: 'Regenerating child chunks will overwrite the current child chunks, including edited chunks and newly added chunks. The regeneration cannot be undone.',
|
||||
regeneratingTitle: 'Regenerating child chunks',
|
||||
|
|
|
|||
|
|
@ -44,6 +44,7 @@ const translation = {
|
|||
openInNewTab: '在新标签页打开',
|
||||
saveAndRegenerate: '保存并重新生成子分段',
|
||||
close: '关闭',
|
||||
view: '查看',
|
||||
viewMore: '查看更多',
|
||||
regenerate: '重新生成',
|
||||
},
|
||||
|
|
|
|||
|
|
@ -351,7 +351,7 @@ const translation = {
|
|||
addAnother: '连续新增',
|
||||
delete: '删除这个分段?',
|
||||
chunkAdded: '新增一个分段',
|
||||
viewAddedChunk: '查看',
|
||||
childChunkAdded: '新增一个子分段',
|
||||
regenerationConfirmTitle: '是否需要重新生成子分段?',
|
||||
regenerationConfirmMessage: '重新生成的子分段将会覆盖当前的子分段,包括编辑过的分段和新添加的分段。重新生成操作无法撤销。',
|
||||
regeneratingTitle: '正在生成子分段',
|
||||
|
|
|
|||
|
|
@ -627,6 +627,7 @@ export type ChildChunkDetail = {
|
|||
content: string
|
||||
word_count: number
|
||||
created_at: number
|
||||
updated_at: number
|
||||
type: ChildChunkType
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue