|
|
|
@ -1,8 +1,8 @@
|
|
|
|
/* eslint-disable no-mixed-operators */
|
|
|
|
/* eslint-disable no-mixed-operators */
|
|
|
|
'use client'
|
|
|
|
'use client'
|
|
|
|
import type { FC, SVGProps } from 'react'
|
|
|
|
import type { FC, SVGProps } from 'react'
|
|
|
|
import React, { useEffect, useState } from 'react'
|
|
|
|
import React, { useCallback, useEffect, useState } from 'react'
|
|
|
|
import { useDebounceFn } from 'ahooks'
|
|
|
|
import { useBoolean, useDebounceFn } from 'ahooks'
|
|
|
|
import { ArrowDownIcon, TrashIcon } from '@heroicons/react/24/outline'
|
|
|
|
import { ArrowDownIcon, TrashIcon } from '@heroicons/react/24/outline'
|
|
|
|
import { ExclamationCircleIcon } from '@heroicons/react/24/solid'
|
|
|
|
import { ExclamationCircleIcon } from '@heroicons/react/24/solid'
|
|
|
|
import { pick } from 'lodash-es'
|
|
|
|
import { pick } from 'lodash-es'
|
|
|
|
@ -11,7 +11,10 @@ import { useRouter } from 'next/navigation'
|
|
|
|
import { useTranslation } from 'react-i18next'
|
|
|
|
import { useTranslation } from 'react-i18next'
|
|
|
|
import cn from 'classnames'
|
|
|
|
import cn from 'classnames'
|
|
|
|
import dayjs from 'dayjs'
|
|
|
|
import dayjs from 'dayjs'
|
|
|
|
|
|
|
|
import { Edit03 } from '../../base/icons/src/vender/solid/general'
|
|
|
|
|
|
|
|
import TooltipPlus from '../../base/tooltip-plus'
|
|
|
|
import s from './style.module.css'
|
|
|
|
import s from './style.module.css'
|
|
|
|
|
|
|
|
import RenameModal from './rename-modal'
|
|
|
|
import Switch from '@/app/components/base/switch'
|
|
|
|
import Switch from '@/app/components/base/switch'
|
|
|
|
import Divider from '@/app/components/base/divider'
|
|
|
|
import Divider from '@/app/components/base/divider'
|
|
|
|
import Popover from '@/app/components/base/popover'
|
|
|
|
import Popover from '@/app/components/base/popover'
|
|
|
|
@ -107,6 +110,7 @@ type OperationName = 'delete' | 'archive' | 'enable' | 'disable' | 'sync' | 'un_
|
|
|
|
export const OperationAction: FC<{
|
|
|
|
export const OperationAction: FC<{
|
|
|
|
embeddingAvailable: boolean
|
|
|
|
embeddingAvailable: boolean
|
|
|
|
detail: {
|
|
|
|
detail: {
|
|
|
|
|
|
|
|
name: string
|
|
|
|
enabled: boolean
|
|
|
|
enabled: boolean
|
|
|
|
archived: boolean
|
|
|
|
archived: boolean
|
|
|
|
id: string
|
|
|
|
id: string
|
|
|
|
@ -164,6 +168,25 @@ export const OperationAction: FC<{
|
|
|
|
onOperate(operationName)
|
|
|
|
onOperate(operationName)
|
|
|
|
}, { wait: 500 })
|
|
|
|
}, { wait: 500 })
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
const [currDocument, setCurrDocument] = useState<{
|
|
|
|
|
|
|
|
id: string
|
|
|
|
|
|
|
|
name: string
|
|
|
|
|
|
|
|
} | null>(null)
|
|
|
|
|
|
|
|
const [isShowRenameModal, {
|
|
|
|
|
|
|
|
setTrue: setShowRenameModalTrue,
|
|
|
|
|
|
|
|
setFalse: setShowRenameModalFalse,
|
|
|
|
|
|
|
|
}] = useBoolean(false)
|
|
|
|
|
|
|
|
const handleShowRenameModal = useCallback((doc: {
|
|
|
|
|
|
|
|
id: string
|
|
|
|
|
|
|
|
name: string
|
|
|
|
|
|
|
|
}) => {
|
|
|
|
|
|
|
|
setCurrDocument(doc)
|
|
|
|
|
|
|
|
setShowRenameModalTrue()
|
|
|
|
|
|
|
|
}, [setShowRenameModalTrue])
|
|
|
|
|
|
|
|
const handleRenamed = useCallback(() => {
|
|
|
|
|
|
|
|
onUpdate()
|
|
|
|
|
|
|
|
}, [onUpdate])
|
|
|
|
|
|
|
|
|
|
|
|
return <div className='flex items-center' onClick={e => e.stopPropagation()}>
|
|
|
|
return <div className='flex items-center' onClick={e => e.stopPropagation()}>
|
|
|
|
{isListScene && !embeddingAvailable && (
|
|
|
|
{isListScene && !embeddingAvailable && (
|
|
|
|
<Switch defaultValue={false} onChange={() => { }} disabled={true} size='md' />
|
|
|
|
<Switch defaultValue={false} onChange={() => { }} disabled={true} size='md' />
|
|
|
|
@ -213,6 +236,15 @@ export const OperationAction: FC<{
|
|
|
|
</>}
|
|
|
|
</>}
|
|
|
|
{!archived && (
|
|
|
|
{!archived && (
|
|
|
|
<>
|
|
|
|
<>
|
|
|
|
|
|
|
|
<div className={s.actionItem} onClick={() => {
|
|
|
|
|
|
|
|
handleShowRenameModal({
|
|
|
|
|
|
|
|
id: detail.id,
|
|
|
|
|
|
|
|
name: detail.name,
|
|
|
|
|
|
|
|
})
|
|
|
|
|
|
|
|
}}>
|
|
|
|
|
|
|
|
<Edit03 className='w-4 h-4 text-gray-500' />
|
|
|
|
|
|
|
|
<span className={s.actionName}>{t('datasetDocuments.list.table.rename')}</span>
|
|
|
|
|
|
|
|
</div>
|
|
|
|
<div className={s.actionItem} onClick={() => router.push(`/datasets/${datasetId}/documents/${detail.id}/settings`)}>
|
|
|
|
<div className={s.actionItem} onClick={() => router.push(`/datasets/${datasetId}/documents/${detail.id}/settings`)}>
|
|
|
|
<SettingsIcon />
|
|
|
|
<SettingsIcon />
|
|
|
|
<span className={s.actionName}>{t('datasetDocuments.list.action.settings')}</span>
|
|
|
|
<span className={s.actionName}>{t('datasetDocuments.list.action.settings')}</span>
|
|
|
|
@ -272,6 +304,16 @@ export const OperationAction: FC<{
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
</Modal>}
|
|
|
|
</Modal>}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
{isShowRenameModal && currDocument && (
|
|
|
|
|
|
|
|
<RenameModal
|
|
|
|
|
|
|
|
datasetId={datasetId}
|
|
|
|
|
|
|
|
documentId={currDocument.id}
|
|
|
|
|
|
|
|
name={currDocument.name}
|
|
|
|
|
|
|
|
onClose={setShowRenameModalFalse}
|
|
|
|
|
|
|
|
onSaved={handleRenamed}
|
|
|
|
|
|
|
|
/>
|
|
|
|
|
|
|
|
)}
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
@ -326,13 +368,30 @@ const DocumentList: FC<IDocumentListProps> = ({ embeddingAvailable, documents =
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
const [currDocument, setCurrDocument] = useState<LocalDoc | null>(null)
|
|
|
|
|
|
|
|
const [isShowRenameModal, {
|
|
|
|
|
|
|
|
setTrue: setShowRenameModalTrue,
|
|
|
|
|
|
|
|
setFalse: setShowRenameModalFalse,
|
|
|
|
|
|
|
|
}] = useBoolean(false)
|
|
|
|
|
|
|
|
const handleShowRenameModal = useCallback((doc: LocalDoc) => {
|
|
|
|
|
|
|
|
setCurrDocument(doc)
|
|
|
|
|
|
|
|
setShowRenameModalTrue()
|
|
|
|
|
|
|
|
}, [setShowRenameModalTrue])
|
|
|
|
|
|
|
|
const handleRenamed = useCallback(() => {
|
|
|
|
|
|
|
|
onUpdate()
|
|
|
|
|
|
|
|
}, [onUpdate])
|
|
|
|
|
|
|
|
|
|
|
|
return (
|
|
|
|
return (
|
|
|
|
<div className='w-full h-full overflow-x-auto'>
|
|
|
|
<div className='w-full h-full overflow-x-auto'>
|
|
|
|
<table className={`min-w-[700px] max-w-full w-full border-collapse border-0 text-sm mt-3 ${s.documentTable}`}>
|
|
|
|
<table className={`min-w-[700px] max-w-full w-full border-collapse border-0 text-sm mt-3 ${s.documentTable}`}>
|
|
|
|
<thead className="h-8 leading-8 border-b border-gray-200 text-gray-500 font-medium text-xs uppercase">
|
|
|
|
<thead className="h-8 leading-8 border-b border-gray-200 text-gray-500 font-medium text-xs uppercase">
|
|
|
|
<tr>
|
|
|
|
<tr>
|
|
|
|
<td className='w-12'>#</td>
|
|
|
|
<td className='w-12'>#</td>
|
|
|
|
<td>{t('datasetDocuments.list.table.header.fileName')}</td>
|
|
|
|
<td>
|
|
|
|
|
|
|
|
<div className='flex'>
|
|
|
|
|
|
|
|
{t('datasetDocuments.list.table.header.fileName')}
|
|
|
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
</td>
|
|
|
|
<td className='w-24'>{t('datasetDocuments.list.table.header.words')}</td>
|
|
|
|
<td className='w-24'>{t('datasetDocuments.list.table.header.words')}</td>
|
|
|
|
<td className='w-44'>{t('datasetDocuments.list.table.header.hitCount')}</td>
|
|
|
|
<td className='w-44'>{t('datasetDocuments.list.table.header.hitCount')}</td>
|
|
|
|
<td className='w-44'>
|
|
|
|
<td className='w-44'>
|
|
|
|
@ -347,7 +406,8 @@ const DocumentList: FC<IDocumentListProps> = ({ embeddingAvailable, documents =
|
|
|
|
</thead>
|
|
|
|
</thead>
|
|
|
|
<tbody className="text-gray-700">
|
|
|
|
<tbody className="text-gray-700">
|
|
|
|
{localDocs.map((doc) => {
|
|
|
|
{localDocs.map((doc) => {
|
|
|
|
const suffix = doc.name.split('.').pop() || 'txt'
|
|
|
|
const isFile = doc.data_source_type === DataSourceType.FILE
|
|
|
|
|
|
|
|
const fileType = isFile ? doc.data_source_detail_dict?.upload_file.extension : ''
|
|
|
|
return <tr
|
|
|
|
return <tr
|
|
|
|
key={doc.id}
|
|
|
|
key={doc.id}
|
|
|
|
className={'border-b border-gray-200 h-8 hover:bg-gray-50 cursor-pointer'}
|
|
|
|
className={'border-b border-gray-200 h-8 hover:bg-gray-50 cursor-pointer'}
|
|
|
|
@ -355,17 +415,33 @@ const DocumentList: FC<IDocumentListProps> = ({ embeddingAvailable, documents =
|
|
|
|
router.push(`/datasets/${datasetId}/documents/${doc.id}`)
|
|
|
|
router.push(`/datasets/${datasetId}/documents/${doc.id}`)
|
|
|
|
}}>
|
|
|
|
}}>
|
|
|
|
<td className='text-left align-middle text-gray-500 text-xs'>{doc.position}</td>
|
|
|
|
<td className='text-left align-middle text-gray-500 text-xs'>{doc.position}</td>
|
|
|
|
<td className={s.tdValue}>
|
|
|
|
<td>
|
|
|
|
|
|
|
|
<div className='group flex items-center justify-between'>
|
|
|
|
|
|
|
|
<span className={s.tdValue}>
|
|
|
|
{
|
|
|
|
{
|
|
|
|
doc?.data_source_type === DataSourceType.NOTION
|
|
|
|
doc?.data_source_type === DataSourceType.NOTION
|
|
|
|
? <NotionIcon className='inline-flex -mt-[3px] mr-1.5 align-middle' type='page' src={doc.data_source_info.notion_page_icon} />
|
|
|
|
? <NotionIcon className='inline-flex -mt-[3px] mr-1.5 align-middle' type='page' src={doc.data_source_info.notion_page_icon} />
|
|
|
|
: <div className={cn(s[`${doc?.data_source_info?.upload_file?.extension ?? suffix}Icon`], s.commonIcon, 'mr-1.5')}></div>
|
|
|
|
: <div className={cn(s[`${doc?.data_source_info?.upload_file?.extension ?? fileType}Icon`], s.commonIcon, 'mr-1.5')}></div>
|
|
|
|
}
|
|
|
|
}
|
|
|
|
{
|
|
|
|
{
|
|
|
|
doc.data_source_type === DataSourceType.NOTION
|
|
|
|
doc.name
|
|
|
|
? <span>{doc.name}</span>
|
|
|
|
|
|
|
|
: <span>{doc?.name?.replace(/\.[^/.]+$/, '')}<span className='text-gray-500'>.{suffix}</span></span>
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
</span>
|
|
|
|
|
|
|
|
<div className='group-hover:flex hidden'>
|
|
|
|
|
|
|
|
<TooltipPlus popupContent={t('datasetDocuments.list.table.rename')}>
|
|
|
|
|
|
|
|
<div
|
|
|
|
|
|
|
|
className='p-1 rounded-md cursor-pointer hover:bg-black/5'
|
|
|
|
|
|
|
|
onClick={(e) => {
|
|
|
|
|
|
|
|
e.stopPropagation()
|
|
|
|
|
|
|
|
handleShowRenameModal(doc)
|
|
|
|
|
|
|
|
}}
|
|
|
|
|
|
|
|
>
|
|
|
|
|
|
|
|
<Edit03 className='w-4 h-4 text-gray-500' />
|
|
|
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
</TooltipPlus>
|
|
|
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
|
|
</td>
|
|
|
|
</td>
|
|
|
|
<td>{renderCount(doc.word_count)}</td>
|
|
|
|
<td>{renderCount(doc.word_count)}</td>
|
|
|
|
<td>{renderCount(doc.hit_count)}</td>
|
|
|
|
<td>{renderCount(doc.hit_count)}</td>
|
|
|
|
@ -383,7 +459,7 @@ const DocumentList: FC<IDocumentListProps> = ({ embeddingAvailable, documents =
|
|
|
|
<OperationAction
|
|
|
|
<OperationAction
|
|
|
|
embeddingAvailable={embeddingAvailable}
|
|
|
|
embeddingAvailable={embeddingAvailable}
|
|
|
|
datasetId={datasetId}
|
|
|
|
datasetId={datasetId}
|
|
|
|
detail={pick(doc, ['enabled', 'archived', 'id', 'data_source_type', 'doc_form'])}
|
|
|
|
detail={pick(doc, ['name', 'enabled', 'archived', 'id', 'data_source_type', 'doc_form'])}
|
|
|
|
onUpdate={onUpdate}
|
|
|
|
onUpdate={onUpdate}
|
|
|
|
/>
|
|
|
|
/>
|
|
|
|
</td>
|
|
|
|
</td>
|
|
|
|
@ -391,6 +467,16 @@ const DocumentList: FC<IDocumentListProps> = ({ embeddingAvailable, documents =
|
|
|
|
})}
|
|
|
|
})}
|
|
|
|
</tbody>
|
|
|
|
</tbody>
|
|
|
|
</table>
|
|
|
|
</table>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
{isShowRenameModal && currDocument && (
|
|
|
|
|
|
|
|
<RenameModal
|
|
|
|
|
|
|
|
datasetId={datasetId}
|
|
|
|
|
|
|
|
documentId={currDocument.id}
|
|
|
|
|
|
|
|
name={currDocument.name}
|
|
|
|
|
|
|
|
onClose={setShowRenameModalFalse}
|
|
|
|
|
|
|
|
onSaved={handleRenamed}
|
|
|
|
|
|
|
|
/>
|
|
|
|
|
|
|
|
)}
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
)
|
|
|
|
)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|