use-batch-edit-document-metadata.ts 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144
  1. import { useBoolean } from 'ahooks'
  2. import { type MetadataBatchEditToServer, type MetadataItemInBatchEdit, type MetadataItemWithEdit, type MetadataItemWithValue, UpdateType } from '../types'
  3. import type { SimpleDocumentDetail } from '@/models/datasets'
  4. import { useMemo } from 'react'
  5. import { useBatchUpdateDocMetadata } from '@/service/knowledge/use-metadata'
  6. import Toast from '@/app/components/base/toast'
  7. import { t } from 'i18next'
  8. type Props = {
  9. datasetId: string
  10. docList: SimpleDocumentDetail[]
  11. onUpdate: () => void
  12. }
  13. const useBatchEditDocumentMetadata = ({
  14. datasetId,
  15. docList,
  16. onUpdate,
  17. }: Props) => {
  18. const [isShowEditModal, {
  19. setTrue: showEditModal,
  20. setFalse: hideEditModal,
  21. }] = useBoolean(false)
  22. const metaDataList: MetadataItemWithValue[][] = (() => {
  23. const res: MetadataItemWithValue[][] = []
  24. docList.forEach((item) => {
  25. if (item.doc_metadata) {
  26. res.push(item.doc_metadata.filter(item => item.id !== 'built-in'))
  27. return
  28. }
  29. res.push([])
  30. })
  31. return res
  32. })()
  33. // To check is key has multiple value
  34. const originalList: MetadataItemInBatchEdit[] = useMemo(() => {
  35. const idNameValue: Record<string, { value: string | number | null, isMultipleValue: boolean }> = {}
  36. const res: MetadataItemInBatchEdit[] = []
  37. metaDataList.forEach((metaData) => {
  38. metaData.forEach((item) => {
  39. if (idNameValue[item.id]?.isMultipleValue)
  40. return
  41. const itemInRes = res.find(i => i.id === item.id)
  42. if (!idNameValue[item.id]) {
  43. idNameValue[item.id] = {
  44. value: item.value,
  45. isMultipleValue: false,
  46. }
  47. }
  48. if (itemInRes && itemInRes.value !== item.value) {
  49. idNameValue[item.id].isMultipleValue = true
  50. itemInRes.isMultipleValue = true
  51. itemInRes.value = null
  52. return
  53. }
  54. if (!itemInRes) {
  55. res.push({
  56. ...item,
  57. isMultipleValue: false,
  58. })
  59. }
  60. })
  61. })
  62. return res
  63. }, [metaDataList])
  64. const formateToBackendList = (editedList: MetadataItemWithEdit[], addedList: MetadataItemInBatchEdit[], isApplyToAllSelectDocument: boolean) => {
  65. const updatedList = editedList.filter((editedItem) => {
  66. return editedItem.updateType === UpdateType.changeValue
  67. })
  68. const removedList = originalList.filter((originalItem) => {
  69. const editedItem = editedList.find(i => i.id === originalItem.id)
  70. if (!editedItem) // removed item
  71. return true
  72. return false
  73. })
  74. const res: MetadataBatchEditToServer = docList.map((item, i) => {
  75. // the new metadata will override the old one
  76. const oldMetadataList = metaDataList[i]
  77. let newMetadataList: MetadataItemWithValue[] = [...oldMetadataList, ...addedList]
  78. .filter((item) => {
  79. return !removedList.find(removedItem => removedItem.id === item.id)
  80. })
  81. .map(item => ({
  82. id: item.id,
  83. name: item.name,
  84. type: item.type,
  85. value: item.value,
  86. }))
  87. if (isApplyToAllSelectDocument) {
  88. // add missing metadata item
  89. updatedList.forEach((editedItem) => {
  90. if (!newMetadataList.find(i => i.id === editedItem.id) && !editedItem.isMultipleValue)
  91. newMetadataList.push(editedItem)
  92. })
  93. }
  94. newMetadataList = newMetadataList.map((item) => {
  95. const editedItem = updatedList.find(i => i.id === item.id)
  96. if (editedItem)
  97. return editedItem
  98. return item
  99. })
  100. return {
  101. document_id: item.id,
  102. metadata_list: newMetadataList,
  103. }
  104. })
  105. return res
  106. }
  107. const { mutateAsync } = useBatchUpdateDocMetadata()
  108. const handleSave = async (editedList: MetadataItemInBatchEdit[], addedList: MetadataItemInBatchEdit[], isApplyToAllSelectDocument: boolean) => {
  109. const backendList = formateToBackendList(editedList, addedList, isApplyToAllSelectDocument)
  110. await mutateAsync({
  111. dataset_id: datasetId,
  112. metadata_list: backendList,
  113. })
  114. onUpdate()
  115. hideEditModal()
  116. Toast.notify({
  117. type: 'success',
  118. message: t('common.actionMsg.modifiedSuccessfully'),
  119. })
  120. }
  121. return {
  122. isShowEditModal,
  123. showEditModal,
  124. hideEditModal,
  125. originalList,
  126. handleSave,
  127. }
  128. }
  129. export default useBatchEditDocumentMetadata