Fix: Optimize the metadata code structure to implement metadata list structure functionality. (#12741)

### What problem does this PR solve?

Fix: Optimize the metadata code structure to implement metadata list
structure functionality.

#11564

### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)
This commit is contained in:
chanx
2026-01-21 16:15:43 +08:00
committed by GitHub
parent e1143d40bc
commit 83e17d8c4a
13 changed files with 315 additions and 251 deletions

View File

@ -18,7 +18,7 @@ import { useFetchKnowledgeBaseConfiguration } from '@/hooks/use-knowledge-reques
import { IModalProps } from '@/interfaces/common';
import { IParserConfig } from '@/interfaces/database/document';
import { IChangeParserConfigRequestBody } from '@/interfaces/request/document';
import { MetadataType } from '@/pages/dataset/components/metedata/hooks/use-manage-modal';
import { MetadataType } from '@/pages/dataset/components/metedata/constant';
import {
AutoMetadata,
ChunkMethodItem,

View File

@ -192,7 +192,7 @@ Example: A 1 KB message with 1024-dim embedding uses ~9 KB. The 5 MB default lim
toMetadataSettingTip: 'Set auto-metadata in Configuration.',
descriptionTip:
'Provide descriptions or examples to guide LLM extract values for this field. If left empty, it will rely on the field name.',
restrictTDefinedValuesTip:
restrictDefinedValuesTip:
'Enum Mode: Restricts LLM extraction to match preset values only. Define values below.',
valueExists:
'Value already exists. Confirm to merge duplicates and combine all associated files.',

View File

@ -183,7 +183,7 @@ export default {
toMetadataSetting: '生成设置',
descriptionTip:
'提供描述或示例来指导大语言模型为此字段提取值。如果留空,将依赖字段名称。',
restrictTDefinedValuesTip:
restrictDefinedValuesTip:
'枚举模式:限制大语言模型提取的值只能匹配预设值。在下方定义值。',
valueExists: '值已存在。确认合并重复项并组合所有关联文件。',
fieldNameExists: '字段名已存在。确认合并重复项并组合所有关联文件。',

View File

@ -0,0 +1,80 @@
import { TFunction } from 'i18next';
import { MetadataValueType } from './interface';
export enum MetadataType {
Manage = 1,
UpdateSingle = 2,
Setting = 3,
SingleFileSetting = 4,
}
export const MetadataDeleteMap = (
t: TFunction<'translation', undefined>,
): Record<
MetadataType,
{
title: string;
warnFieldText: string;
warnValueText: string;
warnFieldName: string;
warnValueName: string;
}
> => {
return {
[MetadataType.Manage]: {
title: t('common.delete') + ' ' + t('knowledgeDetails.metadata.metadata'),
warnFieldText: t('knowledgeDetails.metadata.deleteManageFieldAllWarn'),
warnValueText: t('knowledgeDetails.metadata.deleteManageValueAllWarn'),
warnFieldName: t('knowledgeDetails.metadata.fieldNameExists'),
warnValueName: t('knowledgeDetails.metadata.valueExists'),
},
[MetadataType.Setting]: {
title: t('common.delete') + ' ' + t('knowledgeDetails.metadata.metadata'),
warnFieldText: t('knowledgeDetails.metadata.deleteSettingFieldWarn'),
warnValueText: t('knowledgeDetails.metadata.deleteSettingValueWarn'),
warnFieldName: t('knowledgeDetails.metadata.fieldExists'),
warnValueName: t('knowledgeDetails.metadata.valueExists'),
},
[MetadataType.UpdateSingle]: {
title: t('common.delete') + ' ' + t('knowledgeDetails.metadata.metadata'),
warnFieldText: t('knowledgeDetails.metadata.deleteManageFieldSingleWarn'),
warnValueText: t('knowledgeDetails.metadata.deleteManageValueSingleWarn'),
warnFieldName: t('knowledgeDetails.metadata.fieldSingleNameExists'),
warnValueName: t('knowledgeDetails.metadata.valueSingleExists'),
},
[MetadataType.SingleFileSetting]: {
title: t('common.delete') + ' ' + t('knowledgeDetails.metadata.metadata'),
warnFieldText: t('knowledgeDetails.metadata.deleteSettingFieldWarn'),
warnValueText: t('knowledgeDetails.metadata.deleteSettingValueWarn'),
warnFieldName: t('knowledgeDetails.metadata.fieldExists'),
warnValueName: t('knowledgeDetails.metadata.valueSingleExists'),
},
};
};
export const DEFAULT_VALUE_TYPE: MetadataValueType = 'string';
// const VALUE_TYPES_WITH_ENUM = new Set<MetadataValueType>(['enum']);
export const VALUE_TYPE_LABELS: Record<MetadataValueType, string> = {
string: 'String',
time: 'Time',
number: 'Number',
// bool: 'Bool',
// enum: 'Enum',
list: 'List',
// int: 'Int',
// float: 'Float',
};
export const metadataValueTypeEnum = Object.keys(VALUE_TYPE_LABELS).reduce(
(acc, item) => {
return { ...acc, [item]: item };
},
{} as Record<MetadataValueType, MetadataValueType>,
);
export const metadataValueTypeOptions = Object.entries(VALUE_TYPE_LABELS).map(
([value, label]) => ({ label, value }),
);
export const getMetadataValueTypeLabel = (value?: MetadataValueType) =>
VALUE_TYPE_LABELS[value || DEFAULT_VALUE_TYPE] || VALUE_TYPE_LABELS.string;

View File

@ -1,20 +1,17 @@
import message from '@/components/ui/message';
import { useSetModalState } from '@/hooks/common-hooks';
import { useSelectedIds } from '@/hooks/logic-hooks/use-row-selection';
import {
DocumentApiAction,
useSetDocumentMeta,
} from '@/hooks/use-document-request';
import { DocumentApiAction } from '@/hooks/use-document-request';
import kbService, {
getMetaDataService,
updateMetaData,
} from '@/services/knowledge-service';
import { useQuery, useQueryClient } from '@tanstack/react-query';
import { RowSelectionState } from '@tanstack/react-table';
import { TFunction } from 'i18next';
import { useCallback, useEffect, useMemo, useState } from 'react';
import { useTranslation } from 'react-i18next';
import { useParams } from 'react-router';
import { MetadataType, metadataValueTypeEnum } from '../constant';
import {
IBuiltInMetadataItem,
IMetaDataReturnJSONSettings,
@ -25,141 +22,6 @@ import {
MetadataValueType,
ShowManageMetadataModalProps,
} from '../interface';
export enum MetadataType {
Manage = 1,
UpdateSingle = 2,
Setting = 3,
SingleFileSetting = 4,
}
export const MetadataDeleteMap = (
t: TFunction<'translation', undefined>,
): Record<
MetadataType,
{
title: string;
warnFieldText: string;
warnValueText: string;
warnFieldName: string;
warnValueName: string;
}
> => {
return {
[MetadataType.Manage]: {
title: t('common.delete') + ' ' + t('knowledgeDetails.metadata.metadata'),
warnFieldText: t('knowledgeDetails.metadata.deleteManageFieldAllWarn'),
warnValueText: t('knowledgeDetails.metadata.deleteManageValueAllWarn'),
warnFieldName: t('knowledgeDetails.metadata.fieldNameExists'),
warnValueName: t('knowledgeDetails.metadata.valueExists'),
},
[MetadataType.Setting]: {
title: t('common.delete') + ' ' + t('knowledgeDetails.metadata.metadata'),
warnFieldText: t('knowledgeDetails.metadata.deleteSettingFieldWarn'),
warnValueText: t('knowledgeDetails.metadata.deleteSettingValueWarn'),
warnFieldName: t('knowledgeDetails.metadata.fieldExists'),
warnValueName: t('knowledgeDetails.metadata.valueExists'),
},
[MetadataType.UpdateSingle]: {
title: t('common.delete') + ' ' + t('knowledgeDetails.metadata.metadata'),
warnFieldText: t('knowledgeDetails.metadata.deleteManageFieldSingleWarn'),
warnValueText: t('knowledgeDetails.metadata.deleteManageValueSingleWarn'),
warnFieldName: t('knowledgeDetails.metadata.fieldSingleNameExists'),
warnValueName: t('knowledgeDetails.metadata.valueSingleExists'),
},
[MetadataType.SingleFileSetting]: {
title: t('common.delete') + ' ' + t('knowledgeDetails.metadata.metadata'),
warnFieldText: t('knowledgeDetails.metadata.deleteSettingFieldWarn'),
warnValueText: t('knowledgeDetails.metadata.deleteSettingValueWarn'),
warnFieldName: t('knowledgeDetails.metadata.fieldExists'),
warnValueName: t('knowledgeDetails.metadata.valueSingleExists'),
},
};
};
const DEFAULT_VALUE_TYPE: MetadataValueType = 'string';
// const VALUE_TYPES_WITH_ENUM = new Set<MetadataValueType>(['enum']);
const VALUE_TYPE_LABELS: Record<MetadataValueType, string> = {
string: 'String',
time: 'Time',
number: 'Number',
// bool: 'Bool',
// enum: 'Enum',
// 'list<string>': 'List<String>',
// int: 'Int',
// float: 'Float',
};
export const metadataValueTypeOptions = Object.entries(VALUE_TYPE_LABELS).map(
([value, label]) => ({ label, value }),
);
export const getMetadataValueTypeLabel = (value?: MetadataValueType) =>
VALUE_TYPE_LABELS[value || DEFAULT_VALUE_TYPE] || VALUE_TYPE_LABELS.string;
// export const isMetadataValueTypeWithEnum = (value?: MetadataValueType) =>
// VALUE_TYPES_WITH_ENUM.has(value || DEFAULT_VALUE_TYPE);
// const schemaToValueType = (
// property?: IMetaDataJsonSchemaProperty,
// ): MetadataValueType => {
// if (!property) return DEFAULT_VALUE_TYPE;
// if (
// property.type === 'array' &&
// property.items?.type === 'string' &&
// (property.items.enum?.length || 0) > 0
// ) {
// return 'enum';
// }
// if (property.type === 'boolean') return 'bool';
// if (property.type === 'integer') return 'int';
// if (property.type === 'number') return 'float';
// if (property.type === 'string' && property.format) {
// return 'time';
// }
// if (property.type === 'string' && property.enum?.length) {
// return 'enum';
// }
// return DEFAULT_VALUE_TYPE;
// };
// const valueTypeToSchema = (
// valueType: MetadataValueType,
// description: string,
// values: string[],
// ): IMetaDataJsonSchemaProperty => {
// const schema: IMetaDataJsonSchemaProperty = {
// description: description || '',
// };
// switch (valueType) {
// case 'bool':
// schema.type = 'boolean';
// return schema;
// case 'int':
// schema.type = 'integer';
// return schema;
// case 'float':
// schema.type = 'number';
// return schema;
// case 'time':
// schema.type = 'string';
// schema.format = 'date-time';
// return schema;
// case 'enum':
// schema.type = 'string';
// if (values?.length) {
// schema.enum = values;
// }
// return schema;
// case 'string':
// default:
// schema.type = 'string';
// if (values?.length) {
// schema.enum = values;
// }
// return schema;
// }
// };
export const util = {
changeToMetaDataTableData(data: IMetaDataReturnType): IMetaDataTableData[] {
@ -293,7 +155,22 @@ export const useMetadataOperations = () => {
}, []);
const addUpdateValue = useCallback(
(key: string, originalValue: string, newValue: string) => {
(
key: string,
originalValue: string,
newValue: string | string[],
type?: MetadataValueType,
) => {
let newValuesRes: string | string[];
if (type !== metadataValueTypeEnum['list']) {
if (Array.isArray(newValue) && newValue.length > 0) {
newValuesRes = newValue[0];
} else {
newValuesRes = newValue;
}
} else {
newValuesRes = newValue;
}
setOperations((prev) => {
const existsIndex = prev.updates.findIndex(
(update) => update.key === key && update.match === originalValue,
@ -304,7 +181,8 @@ export const useMetadataOperations = () => {
updatedUpdates[existsIndex] = {
key,
match: originalValue,
value: newValue,
value: newValuesRes,
type,
};
return {
...prev,
@ -315,7 +193,7 @@ export const useMetadataOperations = () => {
...prev,
updates: [
...prev.updates,
{ key, match: originalValue, value: newValue },
{ key, match: originalValue, value: newValuesRes, type },
],
};
});
@ -398,7 +276,7 @@ export const useManageMetaDataModal = (
resetOperations,
} = useMetadataOperations();
const { setDocumentMeta } = useSetDocumentMeta();
// const { setDocumentMeta } = useSetDocumentMeta();
useEffect(() => {
if (fetchTypeList.includes(type)) {
@ -468,6 +346,7 @@ export const useManageMetaDataModal = (
const handleSaveManage = useCallback(
async (callback: () => void) => {
console.log('handleSaveManage', tableData);
const { data: res } = await updateMetaData({
kb_id: id as string,
data: operations,
@ -482,25 +361,25 @@ export const useManageMetaDataModal = (
callback();
}
},
[operations, id, t, queryClient, resetOperations, documentIds],
[operations, id, t, queryClient, resetOperations, documentIds, tableData],
);
const handleSaveUpdateSingle = useCallback(
async (callback: () => void) => {
const reqData = util.tableDataToMetaDataJSON(tableData);
if (otherData?.id) {
const ret = await setDocumentMeta({
documentId: otherData?.id,
meta: JSON.stringify(reqData),
});
if (ret === 0) {
// message.success(t('message.success'));
callback();
}
}
},
[tableData, otherData, setDocumentMeta],
);
// const handleSaveUpdateSingle = useCallback(
// async (callback: () => void) => {
// const reqData = util.tableDataToMetaDataJSON(tableData);
// if (otherData?.id) {
// const ret = await setDocumentMeta({
// documentId: otherData?.id,
// meta: JSON.stringify(reqData),
// });
// if (ret === 0) {
// // message.success(t('message.success'));
// callback();
// }
// }
// },
// [tableData, otherData, setDocumentMeta],
// );
const handleSaveSettings = useCallback(
async (callback: () => void, builtInMetadata?: IBuiltInMetadataItem[]) => {

View File

@ -1,12 +1,16 @@
import { useCallback, useEffect, useState } from 'react';
import { useTranslation } from 'react-i18next';
import { MetadataDeleteMap, MetadataType } from '../hooks/use-manage-modal';
import {
MetadataDeleteMap,
MetadataType,
metadataValueTypeEnum,
} from '../constant';
import { IManageValuesProps, IMetaDataTableData } from '../interface';
export const useManageValues = (props: IManageValuesProps) => {
const {
data,
isAddValueMode,
hideModal,
onSave,
addUpdateValue,
@ -17,7 +21,8 @@ export const useManageValues = (props: IManageValuesProps) => {
const { t } = useTranslation();
const [metaData, setMetaData] = useState<IMetaDataTableData>({
...data,
valueType: data.valueType || 'string',
valueType: data.valueType || metadataValueTypeEnum.string,
values: data.values || [''],
});
const [valueError, setValueError] = useState<Record<string, string>>({
field: '',
@ -31,6 +36,8 @@ export const useManageValues = (props: IManageValuesProps) => {
onOk: () => {},
onCancel: () => {},
});
const [shouldSave, setShouldSave] = useState(false);
const hideDeleteModal = () => {
setDeleteDialogContent({
visible: false,
@ -79,10 +86,11 @@ export const useManageValues = (props: IManageValuesProps) => {
restrictDefinedValues: prev.restrictDefinedValues,
};
}
return {
const newMetadata = {
...prev,
[field]: value,
};
return newMetadata;
});
return true;
},
@ -90,13 +98,13 @@ export const useManageValues = (props: IManageValuesProps) => {
);
// Maintain separate state for each input box
const [tempValues, setTempValues] = useState<string[]>([...data.values]);
const [tempValues, setTempValues] = useState<string[]>(['']);
useEffect(() => {
setTempValues([...data.values]);
setMetaData({
...data,
valueType: data.valueType || 'string',
valueType: data.valueType || metadataValueTypeEnum.string,
});
}, [data]);
@ -119,31 +127,63 @@ export const useManageValues = (props: IManageValuesProps) => {
// handleHideModal();
// return;
// }
onSave(metaData);
handleHideModal();
}, [metaData, onSave, handleHideModal, type, valueError]);
if (isAddValueMode) {
addUpdateValue(
metaData.field,
undefined,
metaData.values,
metaData.valueType,
);
}
// onSave(metaData);
setShouldSave(true);
}, [
metaData,
// onSave,
// handleHideModal,
type,
valueError,
isAddValueMode,
addUpdateValue,
]);
useEffect(() => {
if (shouldSave) {
const timer = setTimeout(() => {
onSave(metaData);
setShouldSave(false);
clearTimeout(timer);
handleHideModal();
}, 100);
}
}, [shouldSave, onSave, handleHideModal, metaData]);
// Handle blur event, synchronize to main state
const handleValueBlur = useCallback(
(values?: string[]) => {
const newValues = values || tempValues;
if (data.values.length > 0) {
if (data.values.length > 0 && !isAddValueMode) {
newValues.forEach((newValue, index) => {
if (index < data.values.length) {
const originalValue = data.values[index];
if (originalValue !== newValue) {
addUpdateValue(metaData.field, originalValue, newValue);
addUpdateValue(
metaData.field,
originalValue,
newValue,
metaData.valueType,
);
}
} else {
if (newValue) {
addUpdateValue(metaData.field, '', newValue);
addUpdateValue(metaData.field, '', newValue, metaData.valueType);
}
}
});
}
handleChange('values', [...new Set([...newValues])]);
},
[handleChange, tempValues, metaData, data, addUpdateValue],
[handleChange, tempValues, metaData, data, addUpdateValue, isAddValueMode],
);
// Handle value changes, only update temporary state
@ -200,13 +240,16 @@ export const useManageValues = (props: IManageValuesProps) => {
[addDeleteValue, metaData],
);
const handleClearValues = useCallback(() => {
setTempValues([]);
setMetaData((prev) => ({
...prev,
values: [],
}));
}, [setTempValues, setMetaData]);
const handleClearValues = useCallback(
(isClearInitialValues = false) => {
setTempValues(isClearInitialValues ? [] : ['']);
setMetaData((prev) => ({
...prev,
values: isClearInitialValues ? [] : [''],
}));
},
[setTempValues, setMetaData],
);
const showDeleteModal = (item: string, callback: () => void) => {
setDeleteDialogContent({

View File

@ -1,5 +1,5 @@
import { ReactNode } from 'react';
import { MetadataType } from './hooks/use-manage-modal';
import { MetadataType } from './constant';
export type IMetaDataReturnType = Record<
string,
| { type: string; values: Array<Array<string | number>> }
@ -36,7 +36,7 @@ export type IMetaDataReturnJSONSettings =
export type MetadataValueType =
| 'string'
// | 'list<string>'
| 'list'
// | 'bool'
// | 'enum'
| 'time'
@ -84,14 +84,16 @@ export interface IManageValuesProps {
isShowValueSwitch?: boolean;
isShowType?: boolean;
isVerticalShowValue?: boolean;
isAddValueMode?: boolean;
data: IMetaDataTableData;
type: MetadataType;
hideModal: () => void;
onSave: (data: IMetaDataTableData) => void;
addUpdateValue: (
key: string,
originalValue: string,
newValue: string,
originalValue: string | undefined,
newValue: string | string[],
type?: MetadataValueType,
) => void;
addDeleteValue: (key: string, value: string) => void;
}
@ -104,7 +106,8 @@ interface DeleteOperation {
interface UpdateOperation {
key: string;
match: string;
value: string;
value: string | string[];
type?: MetadataValueType;
}
export interface MetadataOperations {

View File

@ -1,7 +1,7 @@
import { Button } from '@/components/ui/button';
import { Checkbox } from '@/components/ui/checkbox';
import { Input } from '@/components/ui/input';
import { ColumnDef } from '@tanstack/react-table';
import { ColumnDef, Row, Table } from '@tanstack/react-table';
import {
ListChevronsDownUp,
ListChevronsUpDown,
@ -14,7 +14,7 @@ import {
getMetadataValueTypeLabel,
MetadataDeleteMap,
MetadataType,
} from './hooks/use-manage-modal';
} from './constant';
import { IMetaDataTableData } from './interface';
interface IUseMetadataColumns {
@ -102,7 +102,7 @@ export const useMetadataColumns = ({
? [
{
id: 'select',
header: ({ table }) => (
header: ({ table }: { table: Table<IMetaDataTableData> }) => (
<Checkbox
checked={
table.getIsAllPageRowsSelected() ||
@ -114,7 +114,7 @@ export const useMetadataColumns = ({
aria-label="Select all"
/>
),
cell: ({ row }) => (
cell: ({ row }: { row: Row<IMetaDataTableData> }) => (
<Checkbox
checked={row.getIsSelected()}
onCheckedChange={(value) => row.toggleSelected(!!value)}

View File

@ -35,6 +35,9 @@ import { useHandleMenuClick } from '../../sidebar/hooks';
import {
getMetadataValueTypeLabel,
MetadataType,
metadataValueTypeEnum,
} from './constant';
import {
useManageMetaDataModal,
useOperateData,
} from './hooks/use-manage-modal';
@ -72,7 +75,7 @@ export const ManageMetadataModal = (props: IManageModalProps) => {
field: '',
description: '',
values: [],
valueType: 'string',
valueType: metadataValueTypeEnum.string,
});
const [activeTab, setActiveTab] = useState<MetadataSettingsTab>('generation');
@ -98,12 +101,18 @@ export const ManageMetadataModal = (props: IManageModalProps) => {
);
const { handleMenuClick } = useHandleMenuClick();
const [shouldSave, setShouldSave] = useState(false);
const [isAddValueMode, setIsAddValueMode] = useState(false);
const {
visible: manageValuesVisible,
showModal: showManageValuesModal,
hideModal: hideManageValuesModal,
} = useSetModalState();
const hideManageValuesModalFunc = () => {
setIsAddValueMode(false);
hideManageValuesModal();
};
const isSettingsMode =
metadataType === MetadataType.Setting ||
metadataType === MetadataType.SingleFileSetting ||
@ -166,10 +175,15 @@ export const ManageMetadataModal = (props: IManageModalProps) => {
setValueData({
field: '',
description: '',
values: [],
valueType: 'string',
values:
metadataType === MetadataType.Setting ||
metadataType === MetadataType.SingleFileSetting
? []
: [''],
valueType: metadataValueTypeEnum.string,
});
setCurrentValueIndex(tableData.length || 0);
setIsAddValueMode(true);
showManageValuesModal();
};
const handleEditValueRow = useCallback(
@ -246,6 +260,7 @@ export const ManageMetadataModal = (props: IManageModalProps) => {
return Array.from(fieldMap.values());
});
setShouldSave(true);
setIsAddValueMode(false);
};
useEffect(() => {
@ -254,7 +269,6 @@ export const ManageMetadataModal = (props: IManageModalProps) => {
handleSave({ callback: () => {}, builtInMetadata: builtInSelection });
setShouldSave(false);
}, 0);
console.log('shouldSave');
return () => clearTimeout(timer);
}
}, [tableData, shouldSave, handleSave, builtInSelection]);
@ -302,28 +316,30 @@ export const ManageMetadataModal = (props: IManageModalProps) => {
<div className="flex flex-col gap-2">
<div className="flex items-center justify-between">
<div>{t('knowledgeDetails.metadata.metadata')}</div>
{metadataType === MetadataType.Manage && (
<Button
variant={'ghost'}
className="border border-border-button"
type="button"
onClick={handleMenuClick(Routes.DataSetSetting, {
openMetadata: true,
})}
>
{t('knowledgeDetails.metadata.toMetadataSetting')}
</Button>
)}
{isCanAdd && activeTab !== 'built-in' && (
<Button
variant={'ghost'}
className="border border-border-button"
type="button"
onClick={handAddValueRow}
>
<Plus />
</Button>
)}
<div>
{metadataType === MetadataType.Manage && (
<Button
variant={'ghost'}
className="border border-border-button"
type="button"
onClick={handleMenuClick(Routes.DataSetSetting, {
openMetadata: true,
})}
>
{t('knowledgeDetails.metadata.toMetadataSetting')}
</Button>
)}
{isCanAdd && activeTab !== 'built-in' && (
<Button
variant={'ghost'}
className="border border-border-button"
type="button"
onClick={handAddValueRow}
>
<Plus />
</Button>
)}
</div>
</div>
{rowSelectionIsEmpty || (
@ -538,17 +554,18 @@ export const ManageMetadataModal = (props: IManageModalProps) => {
type={metadataType}
existsKeys={existsKeys}
visible={manageValuesVisible}
hideModal={hideManageValuesModal}
hideModal={hideManageValuesModalFunc}
data={valueData}
onSave={handleSaveValues}
addUpdateValue={addUpdateValue}
addDeleteValue={addDeleteValue}
isEditField={isEditField || isCanAdd}
isAddValue={isAddValue || isCanAdd}
isEditField={isEditField || isAddValueMode}
isAddValue={isAddValue || isAddValueMode}
isShowDescription={isShowDescription}
isShowValueSwitch={isShowValueSwitch}
isShowType={isSettingsMode}
isVerticalShowValue={isVerticalShowValue}
isAddValueMode={isAddValueMode}
// handleDeleteSingleValue={handleDeleteSingleValue}
// handleDeleteSingleRow={handleDeleteSingleRow}
/>

View File

@ -13,7 +13,11 @@ import dayjs from 'dayjs';
import { Plus, Trash2 } from 'lucide-react';
import { memo, useMemo, useRef, useState } from 'react';
import { useTranslation } from 'react-i18next';
import { metadataValueTypeOptions } from './hooks/use-manage-modal';
import {
MetadataType,
metadataValueTypeEnum,
metadataValueTypeOptions,
} from './constant';
import { useManageValues } from './hooks/use-manage-values-modal';
import { IManageValuesProps, MetadataValueType } from './interface';
@ -26,6 +30,7 @@ const ValueInputItem = memo(
onValueChange,
onDelete,
onBlur,
isCanDelete = true,
}: {
item: string;
index: number;
@ -33,6 +38,7 @@ const ValueInputItem = memo(
onValueChange: (index: number, value: string, isUpdate?: boolean) => void;
onDelete: (index: number) => void;
onBlur: (index: number) => void;
isCanDelete?: boolean;
}) => {
const value = useMemo(() => {
if (type === 'time') {
@ -84,14 +90,16 @@ const ValueInputItem = memo(
/>
)}
</div>
<Button
type="button"
variant="delete"
className="border border-border-button px-1 h-6 w-6 rounded-sm"
onClick={() => onDelete(index)}
>
<Trash2 size={14} className="w-4 h-4" />
</Button>
{isCanDelete && (
<Button
type="button"
variant="delete"
className="border border-border-button px-1 h-6 w-6 rounded-sm"
onClick={() => onDelete(index)}
>
<Trash2 size={14} className="w-4 h-4" />
</Button>
)}
</div>
);
},
@ -109,6 +117,7 @@ export const ManageValuesModal = (props: IManageValuesProps) => {
isShowDescription,
isVerticalShowValue,
isShowType,
type: metadataType,
} = props;
const {
metaData,
@ -158,11 +167,33 @@ export const ManageValuesModal = (props: IManageValuesProps) => {
label: 'Type',
type: FormFieldType.Select,
options: metadataValueTypeOptions,
defaultValue: metaData.valueType || 'string',
defaultValue: metaData.valueType || metadataValueTypeEnum.string,
onChange: (value: string) => {
setValueType(value as MetadataValueType);
handleChange('valueType', value);
handleClearValues();
if (
metadataType === MetadataType.Manage ||
metadataType === MetadataType.UpdateSingle
) {
handleClearValues();
}
if (
metadataType === MetadataType.Setting ||
metadataType === MetadataType.SingleFileSetting
) {
if (
value !== metadataValueTypeEnum.list &&
value !== metadataValueTypeEnum.string
) {
handleChange('restrictDefinedValues', false);
handleClearValues(true);
formRef.current?.form.setValue(
'restrictDefinedValues',
false,
);
}
}
},
},
]
@ -188,6 +219,11 @@ export const ManageValuesModal = (props: IManageValuesProps) => {
tooltip: t('knowledgeDetails.metadata.restrictDefinedValuesTip'),
type: FormFieldType.Switch,
defaultValue: metaData.restrictDefinedValues || false,
shouldRender: (formData: any) => {
return (
formData.valueType === 'list' || formData.valueType === 'string'
);
},
onChange: (value: boolean) =>
handleChange('restrictDefinedValues', value),
},
@ -232,17 +268,19 @@ export const ManageValuesModal = (props: IManageValuesProps) => {
<div className="flex flex-col gap-2">
<div className="flex justify-between items-center">
<div>{t('knowledgeDetails.metadata.values')}</div>
{isAddValue && isVerticalShowValue && (
<div>
<Button
variant={'ghost'}
className="border border-border-button"
onClick={handleAddValue}
>
<Plus />
</Button>
</div>
)}
{isAddValue &&
isVerticalShowValue &&
metaData.valueType === metadataValueTypeEnum['list'] && (
<div>
<Button
variant={'ghost'}
className="border border-border-button"
onClick={handleAddValue}
>
<Plus />
</Button>
</div>
)}
</div>
{isVerticalShowValue && (
<div className="flex flex-col gap-2 w-full">
@ -259,7 +297,8 @@ export const ManageValuesModal = (props: IManageValuesProps) => {
handleDelete(idx);
});
}}
onBlur={handleValueBlur}
isCanDelete={tempValues.length > 1}
onBlur={() => handleValueBlur()}
/>
);
})}

View File

@ -34,11 +34,12 @@ import {
} from 'react-hook-form';
import { useLocation } from 'react-router';
import { DataSetContext } from '..';
import { MetadataType } from '../../components/metedata/constant';
import {
MetadataType,
useManageMetadata,
util,
} from '../../components/metedata/hooks/use-manage-modal';
import {
IBuiltInMetadataItem,
IMetaDataReturnJSONSettings,

View File

@ -19,10 +19,8 @@ import { useFetchKnowledgeBaseConfiguration } from '@/hooks/use-knowledge-reques
import { Upload } from 'lucide-react';
import { useEffect, useMemo } from 'react';
import { useTranslation } from 'react-i18next';
import {
MetadataType,
useManageMetadata,
} from '../components/metedata/hooks/use-manage-modal';
import { MetadataType } from '../components/metedata/constant';
import { useManageMetadata } from '../components/metedata/hooks/use-manage-modal';
import { ManageMetadataModal } from '../components/metedata/manage-modal';
import { useKnowledgeBaseContext } from '../contexts/knowledge-base-context';
import { DatasetTable } from './dataset-table';
@ -253,6 +251,8 @@ export default function Dataset() {
// selectedRowKeys={selectedRowKeys}
tableData={tableData}
isCanAdd={metadataConfig.isCanAdd}
isAddValue={metadataConfig.isAddValue}
isVerticalShowValue={metadataConfig.isVerticalShowValue}
isEditField={metadataConfig.isEditField}
isDeleteSingleValue={metadataConfig.isDeleteSingleValue}
type={metadataConfig.type}

View File

@ -16,7 +16,7 @@ import { formatDate } from '@/utils/date';
import { ColumnDef } from '@tanstack/table-core';
import { ArrowUpDown, MonitorUp } from 'lucide-react';
import { useTranslation } from 'react-i18next';
import { MetadataType } from '../components/metedata/hooks/use-manage-modal';
import { MetadataType } from '../components/metedata/constant';
import { ShowManageMetadataModalProps } from '../components/metedata/interface';
import { DatasetActionCell } from './dataset-action-cell';
import { ParsingStatusCell } from './parsing-status-cell';
@ -181,7 +181,9 @@ export function useDatasetTableColumns({
// metadata: util.JSONToMetaDataTableData(
// row.original.meta_fields || {},
// ),
isEditField: false,
isCanAdd: true,
isAddValue: true,
type: MetadataType.UpdateSingle,
record: row.original,
title: (