feat: batch edit can simple save

This commit is contained in:
Joel 2025-03-05 17:56:10 +08:00
parent fd95651551
commit 4ef2816271
3 changed files with 73 additions and 58 deletions

View File

@ -435,7 +435,8 @@ const DocumentList: FC<IDocumentListProps> = ({
originalList, originalList,
handleSave, handleSave,
} = useBatchEditDocumentMetadata({ } = useBatchEditDocumentMetadata({
list: documents, datasetId,
list: documents.filter(item => selectedIds.includes(item.id)),
}) })
useEffect(() => { useEffect(() => {
@ -628,20 +629,20 @@ const DocumentList: FC<IDocumentListProps> = ({
})} })}
</tbody> </tbody>
</table> </table>
{/* {(selectedIds.length > 0) && ( */} {(selectedIds.length > 0) && (
<BatchAction <BatchAction
className='absolute left-0 bottom-16 z-20' className='absolute left-0 bottom-16 z-20'
selectedIds={selectedIds} selectedIds={selectedIds}
onArchive={handleAction(DocumentActionType.archive)} onArchive={handleAction(DocumentActionType.archive)}
onBatchEnable={handleAction(DocumentActionType.enable)} onBatchEnable={handleAction(DocumentActionType.enable)}
onBatchDisable={handleAction(DocumentActionType.disable)} onBatchDisable={handleAction(DocumentActionType.disable)}
onBatchDelete={handleAction(DocumentActionType.delete)} onBatchDelete={handleAction(DocumentActionType.delete)}
onEditMetadata={showEditModal} onEditMetadata={showEditModal}
onCancel={() => { onCancel={() => {
onSelectedIdChange([]) onSelectedIdChange([])
}} }}
/> />
{/* )} */} )}
{/* Show Pagination only if the total is more than the limit */} {/* Show Pagination only if the total is more than the limit */}
{pagination.total && pagination.total > (pagination.limit || 10) && ( {pagination.total && pagination.total > (pagination.limit || 10) && (
<Pagination <Pagination
@ -662,6 +663,7 @@ const DocumentList: FC<IDocumentListProps> = ({
{isShowEditModal && ( {isShowEditModal && (
<EditMetadataBatchModal <EditMetadataBatchModal
datasetId={datasetId}
documentNum={selectedIds.length} documentNum={selectedIds.length}
list={originalList} list={originalList}
onSave={handleSave} onSave={handleSave}

View File

@ -2,8 +2,8 @@
import type { FC } from 'react' import type { FC } from 'react'
import React, { useCallback, useState } from 'react' import React, { useCallback, useState } from 'react'
import Modal from '../../../base/modal' import Modal from '../../../base/modal'
import type { MetadataItemInBatchEdit } from '../types' import type { BuiltInMetadataItem, MetadataItemInBatchEdit } from '../types'
import { DataType, type MetadataItemWithEdit, UpdateType } from '../types' import { type MetadataItemWithEdit, UpdateType } from '../types'
import EditMetadataBatchItem from './edit-row' import EditMetadataBatchItem from './edit-row'
import AddedMetadataItem from './add-row' import AddedMetadataItem from './add-row'
import Button from '../../../base/button' import Button from '../../../base/button'
@ -15,10 +15,14 @@ import { RiQuestionLine } from '@remixicon/react'
import Divider from '@/app/components/base/divider' import Divider from '@/app/components/base/divider'
import AddMetadataButton from '../add-metadata-button' import AddMetadataButton from '../add-metadata-button'
import produce from 'immer' import produce from 'immer'
import useCheckMetadataName from '../hooks/use-check-metadata-name'
import Toast from '@/app/components/base/toast'
import { useCreateMetaData } from '@/service/knowledge/use-metadata'
const i18nPrefix = 'dataset.metadata.batchEditMetadata' const i18nPrefix = 'dataset.metadata.batchEditMetadata'
type Props = { type Props = {
datasetId: string,
documentNum: number documentNum: number
list: MetadataItemInBatchEdit[] list: MetadataItemInBatchEdit[]
onSave: (list: MetadataItemInBatchEdit[], isApplyToAllSelectDocument: boolean) => void onSave: (list: MetadataItemInBatchEdit[], isApplyToAllSelectDocument: boolean) => void
@ -27,12 +31,14 @@ type Props = {
} }
const EditMetadataBatchModal: FC<Props> = ({ const EditMetadataBatchModal: FC<Props> = ({
datasetId,
documentNum, documentNum,
list, list,
onSave, onSave,
onHide, onHide,
onShowManage, onShowManage,
}) => { }) => {
console.log(list)
const { t } = useTranslation() const { t } = useTranslation()
const [templeList, setTempleList] = useState<MetadataItemWithEdit[]>(list) const [templeList, setTempleList] = useState<MetadataItemWithEdit[]>(list)
const handleTemplesChange = useCallback((payload: MetadataItemWithEdit) => { const handleTemplesChange = useCallback((payload: MetadataItemWithEdit) => {
@ -70,15 +76,25 @@ const EditMetadataBatchModal: FC<Props> = ({
setTempleList(newTempleList) setTempleList(newTempleList)
}, [list, templeList]) }, [list, templeList])
const testAddedList: MetadataItemWithEdit[] = [ const { checkName } = useCheckMetadataName()
{ const { mutate: doAddMetaData } = useCreateMetaData(datasetId)
id: '1', name: 'name1', type: DataType.string, value: 'aaa', const handleAddMetaData = useCallback(async (payload: BuiltInMetadataItem) => {
}, const errorMsg = checkName(payload.name).errorMsg
{ if (errorMsg) {
id: '2.1', name: 'num v', type: DataType.number, value: 10, Toast.notify({
}, message: errorMsg,
] type: 'error',
const [addedList, setAddedList] = useState<MetadataItemWithEdit[]>(testAddedList) })
return Promise.reject(new Error(errorMsg))
}
await doAddMetaData(payload)
Toast.notify({
type: 'success',
message: t('common.api.actionSuccess'),
})
}, [checkName, doAddMetaData, t])
const [addedList, setAddedList] = useState<MetadataItemWithEdit[]>([])
const handleAddedListChange = useCallback((payload: MetadataItemWithEdit) => { const handleAddedListChange = useCallback((payload: MetadataItemWithEdit) => {
const newAddedList = addedList.map(i => i.id === payload.id ? payload : i) const newAddedList = addedList.map(i => i.id === payload.id ? payload : i)
setAddedList(newAddedList) setAddedList(newAddedList)
@ -133,12 +149,14 @@ const EditMetadataBatchModal: FC<Props> = ({
</div> </div>
<div className='mt-3'> <div className='mt-3'>
<SelectMetadataModal <SelectMetadataModal
datasetId={datasetId}
popupPlacement='top-start' popupPlacement='top-start'
popupOffset={{ mainAxis: 4, crossAxis: 0 }} popupOffset={{ mainAxis: 4, crossAxis: 0 }}
trigger={ trigger={
<AddMetadataButton /> <AddMetadataButton />
} }
onSave={data => setAddedList([...addedList, data])} onSave={handleAddMetaData}
onSelect={data => setAddedList([...addedList, data as MetadataItemWithEdit])}
onManage={onShowManage} onManage={onShowManage}
/> />
</div> </div>

View File

@ -1,31 +1,17 @@
import { useBoolean } from 'ahooks' import { useBoolean } from 'ahooks'
import type { MetadataBatchEditToServer, MetadataItemInBatchEdit, MetadataItemWithValue } from '../types' import type { MetadataBatchEditToServer, MetadataItemInBatchEdit, MetadataItemWithValue } from '../types'
import { DataType } from '../types'
import type { SimpleDocumentDetail } from '@/models/datasets' import type { SimpleDocumentDetail } from '@/models/datasets'
import { useMemo } from 'react' import { useMemo } from 'react'
import { isEqual } from 'lodash-es' import { isEqual } from 'lodash-es'
// compare import { useBatchUpdateDocMetadata } from '@/service/knowledge/use-metadata'
// original and edited list.
// Use the edited list, except the original and edited value is both multiple value.
const testMetadataList: MetadataItemWithValue[][] = [
[
{ id: 'str-same-value', name: 'name', type: DataType.string, value: 'Joel' },
{ id: 'num', name: 'age', type: DataType.number, value: 10 },
{ id: 'date', name: 'date', type: DataType.time, value: null },
{ id: 'str-with-different-value', name: 'hobby', type: DataType.string, value: 'bbb' },
],
[
{ id: 'str-same-value', name: 'name', type: DataType.string, value: 'Joel' },
{ id: 'str-with-different-value', name: 'hobby', type: DataType.string, value: 'ccc' },
{ id: 'str-extra', name: 'extra', type: DataType.string, value: 'ddd' },
],
]
type Props = { type Props = {
datasetId: string
list: SimpleDocumentDetail[] list: SimpleDocumentDetail[]
} }
const useBatchEditDocumentMetadata = ({ const useBatchEditDocumentMetadata = ({
datasetId,
list, list,
}: Props) => { }: Props) => {
const [isShowEditModal, { const [isShowEditModal, {
@ -33,22 +19,25 @@ const useBatchEditDocumentMetadata = ({
setFalse: hideEditModal, setFalse: hideEditModal,
}] = useBoolean(false) }] = useBoolean(false)
const metaDataList: MetadataItemWithValue[][] = (() => {
const res: MetadataItemWithValue[][] = []
list.forEach((item) => {
if (item.doc_metadata) {
res.push(item.doc_metadata.filter(item => item.id !== 'built-in'))
return
}
res.push([])
})
return res
})()
// To check is key has multiple value
const originalList: MetadataItemInBatchEdit[] = useMemo(() => { const originalList: MetadataItemInBatchEdit[] = useMemo(() => {
const idNameValue: Record<string, { value: string | number | null, isMultipleValue: boolean }> = {} const idNameValue: Record<string, { value: string | number | null, isMultipleValue: boolean }> = {}
// TODO: mock backend data struct
// const metaDataList: MetadataItemWithValue[][] = list.map((item, i) => {
// if (item.doc_metadata)
// return item.doc_metadata
// return testMetadataList[i] || []
// })
const metaDataList = testMetadataList
const res: MetadataItemInBatchEdit[] = [] const res: MetadataItemInBatchEdit[] = []
metaDataList.forEach((metaData) => { metaDataList.forEach((metaData) => {
metaData.forEach((item) => { metaData.forEach((item) => {
// if (item.value === 'ccc') {
// debugger
// }
if (idNameValue[item.id]?.isMultipleValue) if (idNameValue[item.id]?.isMultipleValue)
return return
const itemInRes = res.find(i => i.id === item.id) const itemInRes = res.find(i => i.id === item.id)
@ -74,9 +63,10 @@ const useBatchEditDocumentMetadata = ({
}) })
}) })
return res return res
}, []) }, [metaDataList])
const formateToBackendList = (editedList: MetadataItemInBatchEdit[], isApplyToAllSelectDocument: boolean) => { const formateToBackendList = (editedList: MetadataItemInBatchEdit[], isApplyToAllSelectDocument: boolean) => {
// TODO: add list should be not in updateList; and updated not refresh cash
const updatedList = editedList.filter((editedItem) => { const updatedList = editedList.filter((editedItem) => {
const originalItem = originalList.find(i => i.id === editedItem.id) const originalItem = originalList.find(i => i.id === editedItem.id)
if (!originalItem) // added item if (!originalItem) // added item
@ -94,10 +84,10 @@ const useBatchEditDocumentMetadata = ({
const res: MetadataBatchEditToServer = list.map((item, i) => { const res: MetadataBatchEditToServer = list.map((item, i) => {
// the new metadata will override the old one // the new metadata will override the old one
const oldMetadataList = item.doc_metadata || testMetadataList[i] // TODO: used mock data const oldMetadataList = item.doc_metadata || metaDataList[i]
let newMetadataList: MetadataItemWithValue[] = oldMetadataList let newMetadataList: MetadataItemWithValue[] = oldMetadataList
.filter((item) => { .filter((item) => {
return !removedList.find(removedItem => removedItem.id === item.id) return item.id !== 'built-in' && !removedList.find(removedItem => removedItem.id === item.id)
}) })
.map(item => ({ .map(item => ({
@ -129,9 +119,14 @@ const useBatchEditDocumentMetadata = ({
return res return res
} }
const { mutate } = useBatchUpdateDocMetadata()
const handleSave = (editedList: MetadataItemInBatchEdit[], isApplyToAllSelectDocument: boolean) => { const handleSave = (editedList: MetadataItemInBatchEdit[], isApplyToAllSelectDocument: boolean) => {
const backendList = formateToBackendList(editedList, isApplyToAllSelectDocument) const backendList = formateToBackendList(editedList, isApplyToAllSelectDocument)
console.log(backendList) mutate({
dataset_id: datasetId,
metadata_list: backendList,
})
} }
return { return {