feat: upgrade knowledge metadata (#16063)
Support filter knowledge by metadata. Co-authored-by: Joel <iamjoel007@gmail.com> Co-authored-by: NFish <douxc512@gmail.com>
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
import React, { type FC } from 'react'
|
||||
import { RiArchive2Line, RiCheckboxCircleLine, RiCloseCircleLine, RiDeleteBinLine } from '@remixicon/react'
|
||||
import { RiArchive2Line, RiCheckboxCircleLine, RiCloseCircleLine, RiDeleteBinLine, RiDraftLine } from '@remixicon/react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import { useBoolean } from 'ahooks'
|
||||
import Divider from '@/app/components/base/divider'
|
||||
@@ -14,6 +14,7 @@ type IBatchActionProps = {
|
||||
onBatchDisable: () => void
|
||||
onBatchDelete: () => Promise<void>
|
||||
onArchive?: () => void
|
||||
onEditMetadata?: () => void
|
||||
onCancel: () => void
|
||||
}
|
||||
|
||||
@@ -24,6 +25,7 @@ const BatchAction: FC<IBatchActionProps> = ({
|
||||
onBatchDisable,
|
||||
onArchive,
|
||||
onBatchDelete,
|
||||
onEditMetadata,
|
||||
onCancel,
|
||||
}) => {
|
||||
const { t } = useTranslation()
|
||||
@@ -62,6 +64,15 @@ const BatchAction: FC<IBatchActionProps> = ({
|
||||
{t(`${i18nPrefix}.disable`)}
|
||||
</button>
|
||||
</div>
|
||||
{onEditMetadata && (
|
||||
<div className='flex items-center gap-x-0.5 px-3 py-2'>
|
||||
<RiDraftLine className='w-4 h-4 text-components-button-ghost-text' />
|
||||
<button type='button' className='px-0.5 text-components-button-ghost-text text-[13px] font-medium leading-[16px]' onClick={onEditMetadata}>
|
||||
{t('dataset.metadata.metadata')}
|
||||
</button>
|
||||
</div>
|
||||
)}
|
||||
|
||||
{onArchive && (
|
||||
<div className='flex items-center gap-x-0.5 px-3 py-2'>
|
||||
<RiArchive2Line className='w-4 h-4 text-components-button-ghost-text' />
|
||||
|
||||
@@ -9,7 +9,7 @@ import { OperationAction, StatusItem } from '../list'
|
||||
import DocumentPicker from '../../common/document-picker'
|
||||
import Completed from './completed'
|
||||
import Embedding from './embedding'
|
||||
import Metadata from './metadata'
|
||||
import Metadata from '@/app/components/datasets/metadata/metadata-document'
|
||||
import SegmentAdd, { ProcessStatus } from './segment-add'
|
||||
import BatchModal from './batch-modal'
|
||||
import style from './style.module.css'
|
||||
@@ -281,9 +281,10 @@ const DocumentDetail: FC<Props> = ({ datasetId, documentId }) => {
|
||||
}
|
||||
<FloatRightContainer showClose isOpen={showMetadata} onClose={() => setShowMetadata(false)} isMobile={isMobile} panelClassname='!justify-start' footer={null}>
|
||||
<Metadata
|
||||
className='mr-2 mt-3'
|
||||
datasetId={datasetId}
|
||||
documentId={documentId}
|
||||
docDetail={{ ...documentDetail, ...documentMetadata, doc_type: documentMetadata?.doc_type === 'others' ? '' : documentMetadata?.doc_type } as any}
|
||||
loading={isMetadataLoading}
|
||||
onUpdate={metadataMutate}
|
||||
/>
|
||||
</FloatRightContainer>
|
||||
</div>
|
||||
|
||||
@@ -6,7 +6,7 @@ import { useRouter } from 'next/navigation'
|
||||
import { useDebounce, useDebounceFn } from 'ahooks'
|
||||
import { groupBy } from 'lodash-es'
|
||||
import { PlusIcon } from '@heroicons/react/24/solid'
|
||||
import { RiExternalLinkLine } from '@remixicon/react'
|
||||
import { RiDraftLine, RiExternalLinkLine } from '@remixicon/react'
|
||||
import AutoDisabledDocument from '../common/document-status-with-action/auto-disabled-document'
|
||||
import List from './list'
|
||||
import s from './style.module.css'
|
||||
@@ -26,6 +26,9 @@ import cn from '@/utils/classnames'
|
||||
import { useDocumentList, useInvalidDocumentDetailKey, useInvalidDocumentList } from '@/service/knowledge/use-document'
|
||||
import { useInvalid } from '@/service/use-base'
|
||||
import { useChildSegmentListKey, useSegmentListKey } from '@/service/knowledge/use-segment'
|
||||
import useEditDocumentMetadata from '../metadata/hooks/use-edit-dataset-metadata'
|
||||
import DatasetMetadataDrawer from '../metadata/metadata-dataset/dataset-metadata-drawer'
|
||||
import StatusWithAction from '../common/document-status-with-action/status-with-action'
|
||||
|
||||
const FolderPlusIcon = ({ className }: React.SVGProps<SVGElement>) => {
|
||||
return <svg width="20" height="20" viewBox="0 0 20 20" fill="none" xmlns="http://www.w3.org/2000/svg" className={className ?? ''}>
|
||||
@@ -116,7 +119,7 @@ const Documents: FC<IDocumentsProps> = ({ datasetId }) => {
|
||||
if (totalPages < currPage + 1)
|
||||
setCurrPage(totalPages === 0 ? 0 : totalPages - 1)
|
||||
}
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, [documentsRes])
|
||||
|
||||
const invalidDocumentDetail = useInvalidDocumentDetailKey()
|
||||
@@ -231,6 +234,23 @@ const Documents: FC<IDocumentsProps> = ({ datasetId }) => {
|
||||
handleSearch()
|
||||
}
|
||||
|
||||
const {
|
||||
isShowEditModal: isShowEditMetadataModal,
|
||||
showEditModal: showEditMetadataModal,
|
||||
hideEditModal: hideEditMetadataModal,
|
||||
datasetMetaData,
|
||||
handleAddMetaData,
|
||||
handleRename,
|
||||
handleDeleteMetaData,
|
||||
builtInEnabled,
|
||||
setBuiltInEnabled,
|
||||
builtInMetaData,
|
||||
} = useEditDocumentMetadata({
|
||||
datasetId,
|
||||
dataset,
|
||||
onUpdateDocList: invalidDocumentList,
|
||||
})
|
||||
|
||||
return (
|
||||
<div className='flex flex-col h-full overflow-y-auto'>
|
||||
<div className='flex flex-col justify-center gap-1 px-6 pt-4'>
|
||||
@@ -259,6 +279,25 @@ const Documents: FC<IDocumentsProps> = ({ datasetId }) => {
|
||||
<div className='flex gap-2 justify-center items-center !h-8'>
|
||||
{!isFreePlan && <AutoDisabledDocument datasetId={datasetId} />}
|
||||
<IndexFailed datasetId={datasetId} />
|
||||
{!embeddingAvailable && <StatusWithAction type='warning' description={t('dataset.embeddingModelNotAvailable')} />}
|
||||
{embeddingAvailable && (
|
||||
<Button variant='secondary' className='shrink-0' onClick={showEditMetadataModal}>
|
||||
<RiDraftLine className='size-4 mr-1' />
|
||||
{t('dataset.metadata.metadata')}
|
||||
</Button>
|
||||
)}
|
||||
{isShowEditMetadataModal && (
|
||||
<DatasetMetadataDrawer
|
||||
userMetadata={datasetMetaData || []}
|
||||
onClose={hideEditMetadataModal}
|
||||
onAdd={handleAddMetaData}
|
||||
onRename={handleRename}
|
||||
onRemove={handleDeleteMetaData}
|
||||
builtInMetadata={builtInMetaData || []}
|
||||
isBuiltInEnabled={!!builtInEnabled}
|
||||
onIsBuiltInEnabledChange={setBuiltInEnabled}
|
||||
/>
|
||||
)}
|
||||
{embeddingAvailable && (
|
||||
<Button variant='primary' onClick={routeToDocCreate} className='shrink-0'>
|
||||
<PlusIcon className={cn('h-4 w-4 mr-2 stroke-current')} />
|
||||
@@ -286,6 +325,7 @@ const Documents: FC<IDocumentsProps> = ({ datasetId }) => {
|
||||
current: currPage,
|
||||
onChange: setCurrPage,
|
||||
}}
|
||||
onManageMetadata={showEditMetadataModal}
|
||||
/>
|
||||
: <EmptyElement canAdd={embeddingAvailable} onClick={routeToDocCreate} type={isDataSourceNotion ? 'sync' : 'upload'} />
|
||||
}
|
||||
|
||||
@@ -45,6 +45,8 @@ import Pagination from '@/app/components/base/pagination'
|
||||
import Checkbox from '@/app/components/base/checkbox'
|
||||
import { useDocumentArchive, useDocumentDelete, useDocumentDisable, useDocumentEnable, useDocumentUnArchive, useSyncDocument, useSyncWebsite } from '@/service/knowledge/use-document'
|
||||
import { extensionToFileType } from '@/app/components/datasets/hit-testing/utils/extension-to-file-type'
|
||||
import useBatchEditDocumentMetadata from '../metadata/hooks/use-batch-edit-document-metadata'
|
||||
import EditMetadataBatchModal from '@/app/components/datasets/metadata/edit-metadata-batch/modal'
|
||||
|
||||
export const useIndexStatus = () => {
|
||||
const { t } = useTranslation()
|
||||
@@ -107,7 +109,8 @@ export const StatusItem: FC<{
|
||||
const [e] = await asyncRunSafe<CommonResponse>(opApi({ datasetId, documentId: id }) as Promise<CommonResponse>)
|
||||
if (!e) {
|
||||
notify({ type: 'success', message: t('common.actionMsg.modifiedSuccessfully') })
|
||||
onUpdate?.(operationName)
|
||||
onUpdate?.()
|
||||
// onUpdate?.(operationName)
|
||||
}
|
||||
else { notify({ type: 'error', message: t('common.actionMsg.modifiedUnsuccessfully') }) }
|
||||
}
|
||||
@@ -401,6 +404,7 @@ type IDocumentListProps = {
|
||||
datasetId: string
|
||||
pagination: PaginationProps
|
||||
onUpdate: () => void
|
||||
onManageMetadata: () => void
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -414,6 +418,7 @@ const DocumentList: FC<IDocumentListProps> = ({
|
||||
datasetId,
|
||||
pagination,
|
||||
onUpdate,
|
||||
onManageMetadata,
|
||||
}) => {
|
||||
const { t } = useTranslation()
|
||||
const { formatTime } = useTimestamp()
|
||||
@@ -424,6 +429,17 @@ const DocumentList: FC<IDocumentListProps> = ({
|
||||
const isQAMode = chunkingMode === ChunkingMode.qa
|
||||
const [localDocs, setLocalDocs] = useState<LocalDoc[]>(documents)
|
||||
const [enableSort, setEnableSort] = useState(true)
|
||||
const {
|
||||
isShowEditModal,
|
||||
showEditModal,
|
||||
hideEditModal,
|
||||
originalList,
|
||||
handleSave,
|
||||
} = useBatchEditDocumentMetadata({
|
||||
datasetId,
|
||||
docList: documents.filter(item => selectedIds.includes(item.id)),
|
||||
onUpdate,
|
||||
})
|
||||
|
||||
useEffect(() => {
|
||||
setLocalDocs(documents)
|
||||
@@ -501,18 +517,20 @@ const DocumentList: FC<IDocumentListProps> = ({
|
||||
|
||||
return (
|
||||
<div className='flex flex-col relative w-full h-full'>
|
||||
<div className='grow overflow-x-auto'>
|
||||
<div className='relative grow overflow-x-auto'>
|
||||
<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-divider-subtle text-text-tertiary font-medium text-xs uppercase">
|
||||
<tr>
|
||||
<td className='w-12'>
|
||||
<div className='flex items-center' onClick={e => e.stopPropagation()}>
|
||||
<Checkbox
|
||||
className='shrink-0 mr-2'
|
||||
checked={isAllSelected}
|
||||
mixed={!isAllSelected && isSomeSelected}
|
||||
onCheck={onSelectedAll}
|
||||
/>
|
||||
{embeddingAvailable && (
|
||||
<Checkbox
|
||||
className='shrink-0 mr-2'
|
||||
checked={isAllSelected}
|
||||
mixed={!isAllSelected && isSomeSelected}
|
||||
onCheck={onSelectedAll}
|
||||
/>
|
||||
)}
|
||||
#
|
||||
</div>
|
||||
</td>
|
||||
@@ -625,6 +643,7 @@ const DocumentList: FC<IDocumentListProps> = ({
|
||||
onBatchEnable={handleAction(DocumentActionType.enable)}
|
||||
onBatchDisable={handleAction(DocumentActionType.disable)}
|
||||
onBatchDelete={handleAction(DocumentActionType.delete)}
|
||||
onEditMetadata={showEditModal}
|
||||
onCancel={() => {
|
||||
onSelectedIdChange([])
|
||||
}}
|
||||
@@ -647,6 +666,20 @@ const DocumentList: FC<IDocumentListProps> = ({
|
||||
onSaved={handleRenamed}
|
||||
/>
|
||||
)}
|
||||
|
||||
{isShowEditModal && (
|
||||
<EditMetadataBatchModal
|
||||
datasetId={datasetId}
|
||||
documentNum={selectedIds.length}
|
||||
list={originalList}
|
||||
onSave={handleSave}
|
||||
onHide={hideEditModal}
|
||||
onShowManage={() => {
|
||||
hideEditModal()
|
||||
onManageMetadata()
|
||||
}}
|
||||
/>
|
||||
)}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user