use-metadata-document.ts 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159
  1. import { useBatchUpdateDocMetadata, useDatasetMetaData, useDocumentMetaData } from '@/service/knowledge/use-metadata'
  2. import { useDatasetDetailContext } from '@/context/dataset-detail'
  3. import type { BuiltInMetadataItem } from '../types'
  4. import { DataType, type MetadataItemWithValue } from '../types'
  5. import { useCallback, useState } from 'react'
  6. import Toast from '@/app/components/base/toast'
  7. import type { FullDocumentDetail } from '@/models/datasets'
  8. import { useTranslation } from 'react-i18next'
  9. import { useLanguages, useMetadataMap } from '@/hooks/use-metadata'
  10. import { get } from 'lodash-es'
  11. import { useCreateMetaData } from '@/service/knowledge/use-metadata'
  12. import useCheckMetadataName from './use-check-metadata-name'
  13. type Props = {
  14. datasetId: string
  15. documentId: string
  16. docDetail: FullDocumentDetail
  17. }
  18. const useMetadataDocument = ({
  19. datasetId,
  20. documentId,
  21. docDetail,
  22. }: Props) => {
  23. const { t } = useTranslation()
  24. const { dataset } = useDatasetDetailContext()
  25. const embeddingAvailable = !!dataset?.embedding_available
  26. const { mutateAsync } = useBatchUpdateDocMetadata()
  27. const { checkName } = useCheckMetadataName()
  28. const [isEdit, setIsEdit] = useState(false)
  29. const { data: documentDetail } = useDocumentMetaData({
  30. datasetId,
  31. documentId,
  32. })
  33. const allList = documentDetail?.doc_metadata || []
  34. const list = allList.filter(item => item.id !== 'built-in')
  35. const builtList = allList.filter(item => item.id === 'built-in')
  36. const [tempList, setTempList] = useState<MetadataItemWithValue[]>(list)
  37. const { mutateAsync: doAddMetaData } = useCreateMetaData(datasetId)
  38. const handleSelectMetaData = useCallback((metaData: MetadataItemWithValue) => {
  39. setTempList((prev) => {
  40. const index = prev.findIndex(item => item.id === metaData.id)
  41. if (index === -1)
  42. return [...prev, metaData]
  43. return prev
  44. })
  45. }, [])
  46. const handleAddMetaData = useCallback(async (payload: BuiltInMetadataItem) => {
  47. const errorMsg = checkName(payload.name).errorMsg
  48. if (errorMsg) {
  49. Toast.notify({
  50. message: errorMsg,
  51. type: 'error',
  52. })
  53. return Promise.reject(new Error(errorMsg))
  54. }
  55. await doAddMetaData(payload)
  56. Toast.notify({
  57. type: 'success',
  58. message: t('common.api.actionSuccess'),
  59. })
  60. }, [checkName, doAddMetaData, t])
  61. const hasData = list.length > 0
  62. const handleSave = async () => {
  63. await mutateAsync({
  64. dataset_id: datasetId,
  65. metadata_list: [{
  66. document_id: documentId,
  67. metadata_list: tempList,
  68. }],
  69. })
  70. setIsEdit(false)
  71. Toast.notify({
  72. type: 'success',
  73. message: t('common.api.actionSuccess'),
  74. })
  75. }
  76. const handleCancel = () => {
  77. setTempList(list)
  78. setIsEdit(false)
  79. }
  80. const startToEdit = () => {
  81. setTempList(list)
  82. setIsEdit(true)
  83. }
  84. // built in enabled is set in dataset
  85. const { data: datasetMetaData } = useDatasetMetaData(datasetId)
  86. const builtInEnabled = datasetMetaData?.built_in_field_enabled
  87. // old metadata and technical params
  88. const metadataMap = useMetadataMap()
  89. const languageMap = useLanguages()
  90. const getReadOnlyMetaData = (mainField: 'originInfo' | 'technicalParameters') => {
  91. const fieldMap = metadataMap[mainField]?.subFieldsMap
  92. const sourceData = docDetail
  93. const getTargetMap = (field: string) => {
  94. if (field === 'language')
  95. return languageMap
  96. return {} as any
  97. }
  98. const getTargetValue = (field: string) => {
  99. const val = get(sourceData, field, '')
  100. if (!val && val !== 0)
  101. return '-'
  102. if (fieldMap[field]?.inputType === 'select')
  103. return getTargetMap(field)[val]
  104. if (fieldMap[field]?.render)
  105. return fieldMap[field]?.render?.(val, field === 'hit_count' ? get(sourceData, 'segment_count', 0) as number : undefined)
  106. return val
  107. }
  108. const fieldList = Object.keys(fieldMap).map((key) => {
  109. const field = fieldMap[key]
  110. return {
  111. id: field?.label,
  112. type: DataType.string,
  113. name: field?.label,
  114. value: getTargetValue(key),
  115. }
  116. })
  117. return fieldList
  118. }
  119. const originInfo = getReadOnlyMetaData('originInfo')
  120. const technicalParameters = getReadOnlyMetaData('technicalParameters')
  121. return {
  122. embeddingAvailable,
  123. isEdit,
  124. setIsEdit,
  125. list,
  126. tempList,
  127. setTempList,
  128. handleSelectMetaData,
  129. handleAddMetaData,
  130. hasData,
  131. builtList,
  132. builtInEnabled,
  133. startToEdit,
  134. handleSave,
  135. handleCancel,
  136. originInfo,
  137. technicalParameters,
  138. }
  139. }
  140. export default useMetadataDocument