Files
ragflow/web/src/pages/dataset/components/metedata/hooks/use-manage-values-modal.ts
chanx 4a2978150c Fix:Metadata saving, copywriting and other related issues (#12169)
### What problem does this PR solve?

Fix:Bugs Fixed
- Text overflow issues that caused rendering problems
- Metadata saving, copywriting and other related issues

### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)
2025-12-25 12:12:32 +08:00

209 lines
5.4 KiB
TypeScript

import { useCallback, useEffect, useState } from 'react';
import { useTranslation } from 'react-i18next';
import { MetadataDeleteMap, MetadataType } from '../hooks/use-manage-modal';
import { IManageValuesProps, IMetaDataTableData } from '../interface';
export const useManageValues = (props: IManageValuesProps) => {
const {
data,
isShowValueSwitch,
hideModal,
onSave,
addUpdateValue,
addDeleteValue,
existsKeys,
type,
} = props;
const { t } = useTranslation();
const [metaData, setMetaData] = useState(data);
const [valueError, setValueError] = useState<Record<string, string>>({
field: '',
values: '',
});
const [deleteDialogContent, setDeleteDialogContent] = useState({
visible: false,
title: '',
name: '',
warnText: '',
onOk: () => {},
onCancel: () => {},
});
const hideDeleteModal = () => {
setDeleteDialogContent({
visible: false,
title: '',
name: '',
warnText: '',
onOk: () => {},
onCancel: () => {},
});
};
// Use functional update to avoid closure issues
const handleChange = useCallback(
(field: string, value: any) => {
if (field === 'field' && existsKeys.includes(value)) {
setValueError((prev) => {
return {
...prev,
field:
type === MetadataType.Setting
? t('knowledgeDetails.metadata.fieldExists')
: t('knowledgeDetails.metadata.fieldNameExists'),
};
});
} else if (field === 'field' && !existsKeys.includes(value)) {
setValueError((prev) => {
return {
...prev,
field: '',
};
});
}
setMetaData((prev) => ({
...prev,
[field]: value,
}));
},
[existsKeys, type, t],
);
// Maintain separate state for each input box
const [tempValues, setTempValues] = useState<string[]>([...data.values]);
useEffect(() => {
setTempValues([...data.values]);
setMetaData(data);
}, [data]);
const handleHideModal = useCallback(() => {
hideModal();
setMetaData({} as IMetaDataTableData);
}, [hideModal]);
const handleSave = useCallback(() => {
if (type === MetadataType.Setting && valueError.field) {
return;
}
if (!metaData.restrictDefinedValues && isShowValueSwitch) {
const newMetaData = { ...metaData, values: [] };
onSave(newMetaData);
} else {
onSave(metaData);
}
handleHideModal();
}, [metaData, onSave, handleHideModal, isShowValueSwitch, type, valueError]);
// Handle value changes, only update temporary state
const handleValueChange = useCallback(
(index: number, value: string) => {
setTempValues((prev) => {
if (prev.includes(value)) {
setValueError((prev) => {
return {
...prev,
values: t('knowledgeDetails.metadata.valueExists'),
};
});
} else {
setValueError((prev) => {
return {
...prev,
values: '',
};
});
}
const newValues = [...prev];
newValues[index] = value;
return newValues;
});
},
[t],
);
// Handle blur event, synchronize to main state
const handleValueBlur = useCallback(() => {
// addUpdateValue(metaData.field, [...new Set([...tempValues])]);
tempValues.forEach((newValue, index) => {
if (index < data.values.length) {
const originalValue = data.values[index];
if (originalValue !== newValue) {
addUpdateValue(metaData.field, originalValue, newValue);
}
} else {
if (newValue) {
addUpdateValue(metaData.field, '', newValue);
}
}
});
handleChange('values', [...new Set([...tempValues])]);
}, [handleChange, tempValues, metaData, data, addUpdateValue]);
// Handle delete operation
const handleDelete = useCallback(
(index: number) => {
setTempValues((prev) => {
const newTempValues = [...prev];
addDeleteValue(metaData.field, newTempValues[index]);
newTempValues.splice(index, 1);
return newTempValues;
});
// Synchronize to main state
setMetaData((prev) => {
const newMetaDataValues = [...prev.values];
newMetaDataValues.splice(index, 1);
return {
...prev,
values: newMetaDataValues,
};
});
},
[addDeleteValue, metaData],
);
const showDeleteModal = (item: string, callback: () => void) => {
setDeleteDialogContent({
visible: true,
title: t('common.delete') + ' ' + t('knowledgeDetails.metadata.value'),
name: item,
warnText: MetadataDeleteMap(t)[type as MetadataType].warnValueText,
onOk: () => {
hideDeleteModal();
callback();
},
onCancel: () => {
hideDeleteModal();
},
});
};
// Handle adding new value
const handleAddValue = useCallback(() => {
setTempValues((prev) => [...new Set([...prev, ''])]);
// Synchronize to main state
setMetaData((prev) => ({
...prev,
values: [...new Set([...prev.values, ''])],
}));
}, []);
return {
metaData,
tempValues,
valueError,
deleteDialogContent,
handleChange,
handleValueChange,
handleValueBlur,
handleDelete,
handleAddValue,
showDeleteModal,
handleSave,
handleHideModal,
};
};