import type { FC } from 'react' import type { FileEntity } from '@/app/components/datasets/common/image-uploader/types' import type { SegmentUpdater } from '@/models/datasets' import { RiCloseLine, RiExpandDiagonalLine } from '@remixicon/react' import { memo, useCallback, useState } from 'react' import { useTranslation } from 'react-i18next' import Divider from '@/app/components/base/divider' import { toast } from '@/app/components/base/ui/toast' import ImageUploaderInChunk from '@/app/components/datasets/common/image-uploader/image-uploader-in-chunk' import { useDatasetDetailContextWithSelector } from '@/context/dataset-detail' import { ChunkingMode } from '@/models/datasets' import { useParams } from '@/next/navigation' import { useAddSegment } from '@/service/knowledge/use-segment' import { cn } from '@/utils/classnames' import { formatNumber } from '@/utils/format' import { IndexingType } from '../../create/step-two' import { useSegmentListContext } from './completed' import ActionButtons from './completed/common/action-buttons' import AddAnother from './completed/common/add-another' import ChunkContent from './completed/common/chunk-content' import Dot from './completed/common/dot' import Keywords from './completed/common/keywords' import { SegmentIndexTag } from './completed/common/segment-index-tag' type NewSegmentModalProps = { onCancel: () => void docForm: ChunkingMode onSave: () => void viewNewlyAddedChunk: () => void } const NewSegmentModal: FC = ({ onCancel, docForm, onSave, viewNewlyAddedChunk, }) => { const { t } = useTranslation() const [question, setQuestion] = useState('') const [answer, setAnswer] = useState('') const [attachments, setAttachments] = useState([]) const { datasetId, documentId } = useParams<{ datasetId: string, documentId: string }>() const [keywords, setKeywords] = useState([]) const [loading, setLoading] = useState(false) const [addAnother, setAddAnother] = useState(true) const fullScreen = useSegmentListContext(s => s.fullScreen) const toggleFullScreen = useSegmentListContext(s => s.toggleFullScreen) const indexingTechnique = useDatasetDetailContextWithSelector(s => s.dataset?.indexing_technique) const [imageUploaderKey, setImageUploaderKey] = useState(() => Date.now()) const handleCancel = useCallback((actionType: 'esc' | 'add' = 'esc') => { if (actionType === 'esc' || !addAnother) onCancel() }, [onCancel, addAnother]) const onAttachmentsChange = useCallback((attachments: FileEntity[]) => { setAttachments(attachments) }, []) const { mutateAsync: addSegment } = useAddSegment() const handleSave = useCallback(async () => { const params: SegmentUpdater = { content: '', attachment_ids: [] } if (docForm === ChunkingMode.qa) { if (!question.trim()) { return toast.error(t('segment.questionEmpty', { ns: 'datasetDocuments' })) } if (!answer.trim()) { return toast.error(t('segment.answerEmpty', { ns: 'datasetDocuments' })) } params.content = question params.answer = answer } else { if (!question.trim()) { return toast.error(t('segment.contentEmpty', { ns: 'datasetDocuments' })) } params.content = question } if (keywords?.length) params.keywords = keywords if (attachments.length) params.attachment_ids = attachments.filter(item => Boolean(item.uploadedId)).map(item => item.uploadedId!) setLoading(true) await addSegment({ datasetId, documentId, body: params }, { onSuccess() { toast.success(t('segment.chunkAdded', { ns: 'datasetDocuments' }), { actionProps: { children: t('operation.view', { ns: 'common' }), onClick: viewNewlyAddedChunk, }, }) handleCancel('add') setQuestion('') setAnswer('') setAttachments([]) setImageUploaderKey(Date.now()) setKeywords([]) onSave() }, onSettled() { setLoading(false) }, }) }, [docForm, keywords, addSegment, datasetId, documentId, question, answer, attachments, t, handleCancel, onSave, viewNewlyAddedChunk]) const count = docForm === ChunkingMode.qa ? (question.length + answer.length) : question.length const wordCountText = `${formatNumber(count)} ${t('segment.characters', { ns: 'datasetDocuments', count })}` const isECOIndexing = indexingTechnique === IndexingType.ECONOMICAL return (
{t('segment.addChunk', { ns: 'datasetDocuments' })}
{wordCountText}
{fullScreen && ( <> setAddAnother(!addAnother)} /> )}
setQuestion(question)} onAnswerChange={answer => setAnswer(answer)} isEditMode={true} />
{isECOIndexing && ( setKeywords(keywords)} /> )}
{!fullScreen && (
setAddAnother(!addAnother)} />
)}
) } export default memo(NewSegmentModal)