mirror of
https://github.com/infiniflow/ragflow.git
synced 2026-01-31 23:55:06 +08:00
Feat: metadata settings in KB. (#12662)
### What problem does this PR solve? #11910 ### Type of change - [x] New Feature (non-breaking change which adds functionality)
This commit is contained in:
@ -68,6 +68,8 @@ export interface ParserConfig {
|
|||||||
topn_tags?: number;
|
topn_tags?: number;
|
||||||
graphrag?: { use_graphrag?: boolean };
|
graphrag?: { use_graphrag?: boolean };
|
||||||
enable_metadata?: boolean;
|
enable_metadata?: boolean;
|
||||||
|
metadata?: any;
|
||||||
|
built_in_metadata?: Array<{ key: string; type: string }>;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface IKnowledgeFileParserConfig {
|
export interface IKnowledgeFileParserConfig {
|
||||||
|
|||||||
@ -14,11 +14,14 @@ import { useCallback, useEffect, useState } from 'react';
|
|||||||
import { useTranslation } from 'react-i18next';
|
import { useTranslation } from 'react-i18next';
|
||||||
import { useParams } from 'react-router';
|
import { useParams } from 'react-router';
|
||||||
import {
|
import {
|
||||||
|
IBuiltInMetadataItem,
|
||||||
|
IMetaDataJsonSchemaProperty,
|
||||||
IMetaDataReturnJSONSettings,
|
IMetaDataReturnJSONSettings,
|
||||||
IMetaDataReturnJSONType,
|
IMetaDataReturnJSONType,
|
||||||
IMetaDataReturnType,
|
IMetaDataReturnType,
|
||||||
IMetaDataTableData,
|
IMetaDataTableData,
|
||||||
MetadataOperations,
|
MetadataOperations,
|
||||||
|
MetadataValueType,
|
||||||
ShowManageMetadataModalProps,
|
ShowManageMetadataModalProps,
|
||||||
} from '../interface';
|
} from '../interface';
|
||||||
export enum MetadataType {
|
export enum MetadataType {
|
||||||
@ -71,6 +74,90 @@ export const MetadataDeleteMap = (
|
|||||||
},
|
},
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const DEFAULT_VALUE_TYPE: MetadataValueType = 'string';
|
||||||
|
const VALUE_TYPES_WITH_ENUM = new Set<MetadataValueType>(['enum']);
|
||||||
|
const VALUE_TYPE_LABELS: Record<MetadataValueType, string> = {
|
||||||
|
string: 'String',
|
||||||
|
bool: 'Bool',
|
||||||
|
enum: 'Enum',
|
||||||
|
time: 'Time',
|
||||||
|
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 = {
|
export const util = {
|
||||||
changeToMetaDataTableData(data: IMetaDataReturnType): IMetaDataTableData[] {
|
changeToMetaDataTableData(data: IMetaDataReturnType): IMetaDataTableData[] {
|
||||||
return Object.entries(data).map(([key, value]) => {
|
return Object.entries(data).map(([key, value]) => {
|
||||||
@ -117,25 +204,58 @@ export const util = {
|
|||||||
tableDataToMetaDataSettingJSON(
|
tableDataToMetaDataSettingJSON(
|
||||||
data: IMetaDataTableData[],
|
data: IMetaDataTableData[],
|
||||||
): IMetaDataReturnJSONSettings {
|
): IMetaDataReturnJSONSettings {
|
||||||
return data.map((item) => {
|
const properties = data.reduce<Record<string, IMetaDataJsonSchemaProperty>>(
|
||||||
return {
|
(acc, item) => {
|
||||||
key: item.field,
|
if (!item.field) {
|
||||||
description: item.description,
|
return acc;
|
||||||
enum: item.values,
|
}
|
||||||
};
|
const valueType = item.valueType || DEFAULT_VALUE_TYPE;
|
||||||
});
|
const values =
|
||||||
|
isMetadataValueTypeWithEnum(valueType) && item.restrictDefinedValues
|
||||||
|
? item.values
|
||||||
|
: [];
|
||||||
|
acc[item.field] = valueTypeToSchema(
|
||||||
|
valueType,
|
||||||
|
item.description,
|
||||||
|
values,
|
||||||
|
);
|
||||||
|
return acc;
|
||||||
|
},
|
||||||
|
{},
|
||||||
|
);
|
||||||
|
|
||||||
|
return {
|
||||||
|
type: 'object',
|
||||||
|
properties,
|
||||||
|
additionalProperties: false,
|
||||||
|
};
|
||||||
},
|
},
|
||||||
|
|
||||||
metaDataSettingJSONToMetaDataTableData(
|
metaDataSettingJSONToMetaDataTableData(
|
||||||
data: IMetaDataReturnJSONSettings,
|
data: IMetaDataReturnJSONSettings,
|
||||||
): IMetaDataTableData[] {
|
): IMetaDataTableData[] {
|
||||||
if (!Array.isArray(data)) return [];
|
if (!data) return [];
|
||||||
return data.map((item) => {
|
if (Array.isArray(data)) {
|
||||||
|
return data.map((item) => {
|
||||||
|
return {
|
||||||
|
field: item.key,
|
||||||
|
description: item.description,
|
||||||
|
values: item.enum || [],
|
||||||
|
restrictDefinedValues: !!item.enum?.length,
|
||||||
|
valueType: DEFAULT_VALUE_TYPE,
|
||||||
|
} as IMetaDataTableData;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
const properties = data.properties || {};
|
||||||
|
return Object.entries(properties).map(([key, property]) => {
|
||||||
|
const valueType = schemaToValueType(property);
|
||||||
|
const values = property.enum || property.items?.enum || [];
|
||||||
return {
|
return {
|
||||||
field: item.key,
|
field: key,
|
||||||
description: item.description,
|
description: property.description || '',
|
||||||
values: item.enum,
|
values,
|
||||||
restrictDefinedValues: !!item.enum?.length,
|
restrictDefinedValues: !!values.length,
|
||||||
|
valueType,
|
||||||
} as IMetaDataTableData;
|
} as IMetaDataTableData;
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
@ -384,21 +504,15 @@ export const useManageMetaDataModal = (
|
|||||||
);
|
);
|
||||||
|
|
||||||
const handleSaveSettings = useCallback(
|
const handleSaveSettings = useCallback(
|
||||||
async (callback: () => void) => {
|
async (callback: () => void, builtInMetadata?: IBuiltInMetadataItem[]) => {
|
||||||
const data = util.tableDataToMetaDataSettingJSON(tableData);
|
const data = util.tableDataToMetaDataSettingJSON(tableData);
|
||||||
const { data: res } = await kbService.kbUpdateMetaData({
|
callback?.();
|
||||||
kb_id: id,
|
return {
|
||||||
metadata: data,
|
metadata: data,
|
||||||
enable_metadata: true,
|
builtInMetadata: builtInMetadata || [],
|
||||||
});
|
};
|
||||||
if (res.code === 0) {
|
|
||||||
message.success(t('message.operated'));
|
|
||||||
callback?.();
|
|
||||||
}
|
|
||||||
|
|
||||||
return data;
|
|
||||||
},
|
},
|
||||||
[tableData, id, t],
|
[tableData],
|
||||||
);
|
);
|
||||||
|
|
||||||
const handleSaveSingleFileSettings = useCallback(
|
const handleSaveSingleFileSettings = useCallback(
|
||||||
@ -421,7 +535,13 @@ export const useManageMetaDataModal = (
|
|||||||
);
|
);
|
||||||
|
|
||||||
const handleSave = useCallback(
|
const handleSave = useCallback(
|
||||||
async ({ callback }: { callback: () => void }) => {
|
async ({
|
||||||
|
callback,
|
||||||
|
builtInMetadata,
|
||||||
|
}: {
|
||||||
|
callback: () => void;
|
||||||
|
builtInMetadata?: string[];
|
||||||
|
}) => {
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case MetadataType.UpdateSingle:
|
case MetadataType.UpdateSingle:
|
||||||
handleSaveUpdateSingle(callback);
|
handleSaveUpdateSingle(callback);
|
||||||
@ -430,7 +550,7 @@ export const useManageMetaDataModal = (
|
|||||||
handleSaveManage(callback);
|
handleSaveManage(callback);
|
||||||
break;
|
break;
|
||||||
case MetadataType.Setting:
|
case MetadataType.Setting:
|
||||||
return handleSaveSettings(callback);
|
return handleSaveSettings(callback, builtInMetadata);
|
||||||
case MetadataType.SingleFileSetting:
|
case MetadataType.SingleFileSetting:
|
||||||
return handleSaveSingleFileSettings(callback);
|
return handleSaveSingleFileSettings(callback);
|
||||||
default:
|
default:
|
||||||
|
|||||||
@ -1,13 +1,16 @@
|
|||||||
import { useCallback, useEffect, useState } from 'react';
|
import { useCallback, useEffect, useState } from 'react';
|
||||||
import { useTranslation } from 'react-i18next';
|
import { useTranslation } from 'react-i18next';
|
||||||
import { MetadataDeleteMap, MetadataType } from '../hooks/use-manage-modal';
|
import {
|
||||||
|
isMetadataValueTypeWithEnum,
|
||||||
|
MetadataDeleteMap,
|
||||||
|
MetadataType,
|
||||||
|
} from '../hooks/use-manage-modal';
|
||||||
import { IManageValuesProps, IMetaDataTableData } from '../interface';
|
import { IManageValuesProps, IMetaDataTableData } from '../interface';
|
||||||
|
|
||||||
export const useManageValues = (props: IManageValuesProps) => {
|
export const useManageValues = (props: IManageValuesProps) => {
|
||||||
const {
|
const {
|
||||||
data,
|
data,
|
||||||
|
|
||||||
isShowValueSwitch,
|
|
||||||
hideModal,
|
hideModal,
|
||||||
onSave,
|
onSave,
|
||||||
addUpdateValue,
|
addUpdateValue,
|
||||||
@ -16,7 +19,10 @@ export const useManageValues = (props: IManageValuesProps) => {
|
|||||||
type,
|
type,
|
||||||
} = props;
|
} = props;
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
const [metaData, setMetaData] = useState(data);
|
const [metaData, setMetaData] = useState<IMetaDataTableData>({
|
||||||
|
...data,
|
||||||
|
valueType: data.valueType || 'string',
|
||||||
|
});
|
||||||
const [valueError, setValueError] = useState<Record<string, string>>({
|
const [valueError, setValueError] = useState<Record<string, string>>({
|
||||||
field: '',
|
field: '',
|
||||||
values: '',
|
values: '',
|
||||||
@ -61,10 +67,28 @@ export const useManageValues = (props: IManageValuesProps) => {
|
|||||||
};
|
};
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
setMetaData((prev) => ({
|
setMetaData((prev) => {
|
||||||
...prev,
|
if (field === 'valueType') {
|
||||||
[field]: value,
|
const nextValueType = (value ||
|
||||||
}));
|
'string') as IMetaDataTableData['valueType'];
|
||||||
|
const supportsEnum = isMetadataValueTypeWithEnum(nextValueType);
|
||||||
|
if (!supportsEnum) {
|
||||||
|
setTempValues([]);
|
||||||
|
}
|
||||||
|
return {
|
||||||
|
...prev,
|
||||||
|
valueType: nextValueType,
|
||||||
|
values: supportsEnum ? prev.values : [],
|
||||||
|
restrictDefinedValues: supportsEnum
|
||||||
|
? prev.restrictDefinedValues || nextValueType === 'enum'
|
||||||
|
: false,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
return {
|
||||||
|
...prev,
|
||||||
|
[field]: value,
|
||||||
|
};
|
||||||
|
});
|
||||||
},
|
},
|
||||||
[existsKeys, type, t],
|
[existsKeys, type, t],
|
||||||
);
|
);
|
||||||
@ -74,7 +98,10 @@ export const useManageValues = (props: IManageValuesProps) => {
|
|||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
setTempValues([...data.values]);
|
setTempValues([...data.values]);
|
||||||
setMetaData(data);
|
setMetaData({
|
||||||
|
...data,
|
||||||
|
valueType: data.valueType || 'string',
|
||||||
|
});
|
||||||
}, [data]);
|
}, [data]);
|
||||||
|
|
||||||
const handleHideModal = useCallback(() => {
|
const handleHideModal = useCallback(() => {
|
||||||
@ -86,14 +113,19 @@ export const useManageValues = (props: IManageValuesProps) => {
|
|||||||
if (type === MetadataType.Setting && valueError.field) {
|
if (type === MetadataType.Setting && valueError.field) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (!metaData.restrictDefinedValues && isShowValueSwitch) {
|
const supportsEnum = isMetadataValueTypeWithEnum(metaData.valueType);
|
||||||
const newMetaData = { ...metaData, values: [] };
|
if (!supportsEnum) {
|
||||||
onSave(newMetaData);
|
onSave({
|
||||||
} else {
|
...metaData,
|
||||||
onSave(metaData);
|
values: [],
|
||||||
|
restrictDefinedValues: false,
|
||||||
|
});
|
||||||
|
handleHideModal();
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
onSave(metaData);
|
||||||
handleHideModal();
|
handleHideModal();
|
||||||
}, [metaData, onSave, handleHideModal, isShowValueSwitch, type, valueError]);
|
}, [metaData, onSave, handleHideModal, type, valueError]);
|
||||||
|
|
||||||
// Handle value changes, only update temporary state
|
// Handle value changes, only update temporary state
|
||||||
const handleValueChange = useCallback(
|
const handleValueChange = useCallback(
|
||||||
|
|||||||
@ -11,13 +11,44 @@ export interface IMetaDataReturnJSONSettingItem {
|
|||||||
description?: string;
|
description?: string;
|
||||||
enum?: string[];
|
enum?: string[];
|
||||||
}
|
}
|
||||||
export type IMetaDataReturnJSONSettings = Array<IMetaDataReturnJSONSettingItem>;
|
export interface IMetaDataJsonSchemaProperty {
|
||||||
|
type?: string;
|
||||||
|
description?: string;
|
||||||
|
enum?: string[];
|
||||||
|
items?: {
|
||||||
|
type?: string;
|
||||||
|
enum?: string[];
|
||||||
|
};
|
||||||
|
format?: string;
|
||||||
|
}
|
||||||
|
export interface IMetaDataJsonSchema {
|
||||||
|
type?: 'object';
|
||||||
|
properties?: Record<string, IMetaDataJsonSchemaProperty>;
|
||||||
|
additionalProperties?: boolean;
|
||||||
|
}
|
||||||
|
export type IMetaDataReturnJSONSettings =
|
||||||
|
| IMetaDataJsonSchema
|
||||||
|
| Array<IMetaDataReturnJSONSettingItem>;
|
||||||
|
|
||||||
|
export type MetadataValueType =
|
||||||
|
| 'string'
|
||||||
|
| 'bool'
|
||||||
|
| 'enum'
|
||||||
|
| 'time'
|
||||||
|
| 'int'
|
||||||
|
| 'float';
|
||||||
|
|
||||||
export type IMetaDataTableData = {
|
export type IMetaDataTableData = {
|
||||||
field: string;
|
field: string;
|
||||||
description: string;
|
description: string;
|
||||||
restrictDefinedValues?: boolean;
|
restrictDefinedValues?: boolean;
|
||||||
values: string[];
|
values: string[];
|
||||||
|
valueType?: MetadataValueType;
|
||||||
|
};
|
||||||
|
|
||||||
|
export type IBuiltInMetadataItem = {
|
||||||
|
key: string;
|
||||||
|
type: MetadataValueType;
|
||||||
};
|
};
|
||||||
|
|
||||||
export type IManageModalProps = {
|
export type IManageModalProps = {
|
||||||
@ -34,6 +65,7 @@ export type IManageModalProps = {
|
|||||||
isAddValue?: boolean;
|
isAddValue?: boolean;
|
||||||
isShowValueSwitch?: boolean;
|
isShowValueSwitch?: boolean;
|
||||||
isVerticalShowValue?: boolean;
|
isVerticalShowValue?: boolean;
|
||||||
|
builtInMetadata?: IBuiltInMetadataItem[];
|
||||||
success?: (data: any) => void;
|
success?: (data: any) => void;
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -45,6 +77,7 @@ export interface IManageValuesProps {
|
|||||||
isAddValue?: boolean;
|
isAddValue?: boolean;
|
||||||
isShowDescription?: boolean;
|
isShowDescription?: boolean;
|
||||||
isShowValueSwitch?: boolean;
|
isShowValueSwitch?: boolean;
|
||||||
|
isShowType?: boolean;
|
||||||
isVerticalShowValue?: boolean;
|
isVerticalShowValue?: boolean;
|
||||||
data: IMetaDataTableData;
|
data: IMetaDataTableData;
|
||||||
type: MetadataType;
|
type: MetadataType;
|
||||||
@ -81,6 +114,7 @@ export type ShowManageMetadataModalProps = Partial<IManageModalProps> & {
|
|||||||
isCanAdd: boolean;
|
isCanAdd: boolean;
|
||||||
type: MetadataType;
|
type: MetadataType;
|
||||||
record?: Record<string, any>;
|
record?: Record<string, any>;
|
||||||
|
builtInMetadata?: IBuiltInMetadataItem[];
|
||||||
options?: ShowManageMetadataModalOptions;
|
options?: ShowManageMetadataModalOptions;
|
||||||
title?: ReactNode | string;
|
title?: ReactNode | string;
|
||||||
isDeleteSingleValue?: boolean;
|
isDeleteSingleValue?: boolean;
|
||||||
|
|||||||
@ -7,6 +7,7 @@ import Empty from '@/components/empty/empty';
|
|||||||
import { Button } from '@/components/ui/button';
|
import { Button } from '@/components/ui/button';
|
||||||
import { Input } from '@/components/ui/input';
|
import { Input } from '@/components/ui/input';
|
||||||
import { Modal } from '@/components/ui/modal/modal';
|
import { Modal } from '@/components/ui/modal/modal';
|
||||||
|
import { Switch } from '@/components/ui/switch';
|
||||||
import {
|
import {
|
||||||
Table,
|
Table,
|
||||||
TableBody,
|
TableBody,
|
||||||
@ -15,6 +16,7 @@ import {
|
|||||||
TableHeader,
|
TableHeader,
|
||||||
TableRow,
|
TableRow,
|
||||||
} from '@/components/ui/table';
|
} from '@/components/ui/table';
|
||||||
|
import { Tabs, TabsContent, TabsList, TabsTrigger } from '@/components/ui/tabs';
|
||||||
import { useSetModalState } from '@/hooks/common-hooks';
|
import { useSetModalState } from '@/hooks/common-hooks';
|
||||||
import { Routes } from '@/routes';
|
import { Routes } from '@/routes';
|
||||||
import {
|
import {
|
||||||
@ -39,11 +41,19 @@ import { useHandleMenuClick } from '../../sidebar/hooks';
|
|||||||
import {
|
import {
|
||||||
MetadataDeleteMap,
|
MetadataDeleteMap,
|
||||||
MetadataType,
|
MetadataType,
|
||||||
|
getMetadataValueTypeLabel,
|
||||||
|
isMetadataValueTypeWithEnum,
|
||||||
useManageMetaDataModal,
|
useManageMetaDataModal,
|
||||||
} from './hooks/use-manage-modal';
|
} from './hooks/use-manage-modal';
|
||||||
import { IManageModalProps, IMetaDataTableData } from './interface';
|
import {
|
||||||
|
IBuiltInMetadataItem,
|
||||||
|
IManageModalProps,
|
||||||
|
IMetaDataTableData,
|
||||||
|
} from './interface';
|
||||||
import { ManageValuesModal } from './manage-values-modal';
|
import { ManageValuesModal } from './manage-values-modal';
|
||||||
|
|
||||||
|
type MetadataSettingsTab = 'generation' | 'built-in';
|
||||||
|
|
||||||
export const ManageMetadataModal = (props: IManageModalProps) => {
|
export const ManageMetadataModal = (props: IManageModalProps) => {
|
||||||
const {
|
const {
|
||||||
title,
|
title,
|
||||||
@ -59,6 +69,7 @@ export const ManageMetadataModal = (props: IManageModalProps) => {
|
|||||||
isShowDescription = false,
|
isShowDescription = false,
|
||||||
isShowValueSwitch = false,
|
isShowValueSwitch = false,
|
||||||
isVerticalShowValue = true,
|
isVerticalShowValue = true,
|
||||||
|
builtInMetadata,
|
||||||
success,
|
success,
|
||||||
} = props;
|
} = props;
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
@ -66,10 +77,15 @@ export const ManageMetadataModal = (props: IManageModalProps) => {
|
|||||||
field: '',
|
field: '',
|
||||||
description: '',
|
description: '',
|
||||||
values: [],
|
values: [],
|
||||||
|
valueType: 'string',
|
||||||
});
|
});
|
||||||
|
|
||||||
const [expanded, setExpanded] = useState(true);
|
const [expanded, setExpanded] = useState(true);
|
||||||
|
const [activeTab, setActiveTab] = useState<MetadataSettingsTab>('generation');
|
||||||
const [currentValueIndex, setCurrentValueIndex] = useState<number>(0);
|
const [currentValueIndex, setCurrentValueIndex] = useState<number>(0);
|
||||||
|
const [builtInSelection, setBuiltInSelection] = useState<
|
||||||
|
IBuiltInMetadataItem[]
|
||||||
|
>([]);
|
||||||
const [deleteDialogContent, setDeleteDialogContent] = useState({
|
const [deleteDialogContent, setDeleteDialogContent] = useState({
|
||||||
visible: false,
|
visible: false,
|
||||||
title: '',
|
title: '',
|
||||||
@ -111,6 +127,62 @@ export const ManageMetadataModal = (props: IManageModalProps) => {
|
|||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const isSettingsMode =
|
||||||
|
metadataType === MetadataType.Setting ||
|
||||||
|
metadataType === MetadataType.SingleFileSetting;
|
||||||
|
const showTypeColumn = isSettingsMode;
|
||||||
|
const builtInRows = useMemo(
|
||||||
|
() => [
|
||||||
|
{
|
||||||
|
field: 'update_time',
|
||||||
|
valueType: 'time',
|
||||||
|
description: t('knowledgeConfiguration.builtIn'),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
field: 'file_name',
|
||||||
|
valueType: 'string',
|
||||||
|
description: t('knowledgeConfiguration.builtIn'),
|
||||||
|
},
|
||||||
|
],
|
||||||
|
[t],
|
||||||
|
);
|
||||||
|
const builtInTypeByKey = useMemo(
|
||||||
|
() =>
|
||||||
|
new Map(
|
||||||
|
builtInRows.map((row) => [
|
||||||
|
row.field,
|
||||||
|
row.valueType as IBuiltInMetadataItem['type'],
|
||||||
|
]),
|
||||||
|
),
|
||||||
|
[builtInRows],
|
||||||
|
);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (!visible) return;
|
||||||
|
setBuiltInSelection(
|
||||||
|
(builtInMetadata || []).map((item) => {
|
||||||
|
if (typeof item === 'string') {
|
||||||
|
return {
|
||||||
|
key: item,
|
||||||
|
type: builtInTypeByKey.get(item) || 'string',
|
||||||
|
};
|
||||||
|
}
|
||||||
|
return {
|
||||||
|
key: item.key,
|
||||||
|
type: (item.type ||
|
||||||
|
builtInTypeByKey.get(item.key) ||
|
||||||
|
'string') as IBuiltInMetadataItem['type'],
|
||||||
|
};
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
setActiveTab('generation');
|
||||||
|
}, [builtInMetadata, builtInTypeByKey, visible]);
|
||||||
|
|
||||||
|
const builtInSelectionKeys = useMemo(
|
||||||
|
() => new Set(builtInSelection.map((item) => item.key)),
|
||||||
|
[builtInSelection],
|
||||||
|
);
|
||||||
|
|
||||||
const handleEditValue = (field: string, value: string) => {
|
const handleEditValue = (field: string, value: string) => {
|
||||||
setEditingValue({ field, value, newValue: value });
|
setEditingValue({ field, value, newValue: value });
|
||||||
};
|
};
|
||||||
@ -141,6 +213,7 @@ export const ManageMetadataModal = (props: IManageModalProps) => {
|
|||||||
field: '',
|
field: '',
|
||||||
description: '',
|
description: '',
|
||||||
values: [],
|
values: [],
|
||||||
|
valueType: 'string',
|
||||||
});
|
});
|
||||||
setCurrentValueIndex(tableData.length || 0);
|
setCurrentValueIndex(tableData.length || 0);
|
||||||
showManageValuesModal();
|
showManageValuesModal();
|
||||||
@ -165,6 +238,21 @@ export const ManageMetadataModal = (props: IManageModalProps) => {
|
|||||||
</div>
|
</div>
|
||||||
),
|
),
|
||||||
},
|
},
|
||||||
|
...(showTypeColumn
|
||||||
|
? ([
|
||||||
|
{
|
||||||
|
accessorKey: 'valueType',
|
||||||
|
header: () => <span>Type</span>,
|
||||||
|
cell: ({ row }) => (
|
||||||
|
<div className="text-sm">
|
||||||
|
{getMetadataValueTypeLabel(
|
||||||
|
row.original.valueType as IMetaDataTableData['valueType'],
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
),
|
||||||
|
},
|
||||||
|
] as ColumnDef<IMetaDataTableData>[])
|
||||||
|
: []),
|
||||||
{
|
{
|
||||||
accessorKey: 'description',
|
accessorKey: 'description',
|
||||||
header: () => <span>{t('knowledgeDetails.metadata.description')}</span>,
|
header: () => <span>{t('knowledgeDetails.metadata.description')}</span>,
|
||||||
@ -196,8 +284,11 @@ export const ManageMetadataModal = (props: IManageModalProps) => {
|
|||||||
),
|
),
|
||||||
cell: ({ row }) => {
|
cell: ({ row }) => {
|
||||||
const values = row.getValue('values') as Array<string>;
|
const values = row.getValue('values') as Array<string>;
|
||||||
|
const supportsEnum = isMetadataValueTypeWithEnum(
|
||||||
|
row.original.valueType,
|
||||||
|
);
|
||||||
|
|
||||||
if (!Array.isArray(values) || values.length === 0) {
|
if (!supportsEnum || !Array.isArray(values) || values.length === 0) {
|
||||||
return <div></div>;
|
return <div></div>;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -342,7 +433,7 @@ export const ManageMetadataModal = (props: IManageModalProps) => {
|
|||||||
},
|
},
|
||||||
];
|
];
|
||||||
if (!isShowDescription) {
|
if (!isShowDescription) {
|
||||||
cols.splice(1, 1);
|
return cols.filter((col) => col.accessorKey !== 'description');
|
||||||
}
|
}
|
||||||
return cols;
|
return cols;
|
||||||
}, [
|
}, [
|
||||||
@ -356,6 +447,7 @@ export const ManageMetadataModal = (props: IManageModalProps) => {
|
|||||||
expanded,
|
expanded,
|
||||||
editingValue,
|
editingValue,
|
||||||
saveEditedValue,
|
saveEditedValue,
|
||||||
|
showTypeColumn,
|
||||||
]);
|
]);
|
||||||
|
|
||||||
const table = useReactTable({
|
const table = useReactTable({
|
||||||
@ -393,7 +485,11 @@ export const ManageMetadataModal = (props: IManageModalProps) => {
|
|||||||
const mergedValues = [
|
const mergedValues = [
|
||||||
...new Set([...existingItem.values, ...item.values]),
|
...new Set([...existingItem.values, ...item.values]),
|
||||||
];
|
];
|
||||||
fieldMap.set(item.field, { ...existingItem, values: mergedValues });
|
fieldMap.set(item.field, {
|
||||||
|
...existingItem,
|
||||||
|
...item,
|
||||||
|
values: mergedValues,
|
||||||
|
});
|
||||||
} else {
|
} else {
|
||||||
fieldMap.set(item.field, item);
|
fieldMap.set(item.field, item);
|
||||||
}
|
}
|
||||||
@ -407,13 +503,13 @@ export const ManageMetadataModal = (props: IManageModalProps) => {
|
|||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (shouldSave) {
|
if (shouldSave) {
|
||||||
const timer = setTimeout(() => {
|
const timer = setTimeout(() => {
|
||||||
handleSave({ callback: () => {} });
|
handleSave({ callback: () => {}, builtInMetadata: builtInSelection });
|
||||||
setShouldSave(false);
|
setShouldSave(false);
|
||||||
}, 0);
|
}, 0);
|
||||||
|
|
||||||
return () => clearTimeout(timer);
|
return () => clearTimeout(timer);
|
||||||
}
|
}
|
||||||
}, [tableData, shouldSave, handleSave]);
|
}, [tableData, shouldSave, handleSave, builtInSelection]);
|
||||||
|
|
||||||
const existsKeys = useMemo(() => {
|
const existsKeys = useMemo(() => {
|
||||||
return tableData.map((item) => item.field);
|
return tableData.map((item) => item.field);
|
||||||
@ -428,7 +524,10 @@ export const ManageMetadataModal = (props: IManageModalProps) => {
|
|||||||
maskClosable={false}
|
maskClosable={false}
|
||||||
okText={t('common.save')}
|
okText={t('common.save')}
|
||||||
onOk={async () => {
|
onOk={async () => {
|
||||||
const res = await handleSave({ callback: hideModal });
|
const res = await handleSave({
|
||||||
|
callback: hideModal,
|
||||||
|
builtInMetadata: builtInSelection,
|
||||||
|
});
|
||||||
console.log('data', res);
|
console.log('data', res);
|
||||||
success?.(res);
|
success?.(res);
|
||||||
}}
|
}}
|
||||||
@ -449,7 +548,7 @@ export const ManageMetadataModal = (props: IManageModalProps) => {
|
|||||||
{t('knowledgeDetails.metadata.toMetadataSetting')}
|
{t('knowledgeDetails.metadata.toMetadataSetting')}
|
||||||
</Button>
|
</Button>
|
||||||
)}
|
)}
|
||||||
{isCanAdd && (
|
{isCanAdd && activeTab !== 'built-in' && (
|
||||||
<Button
|
<Button
|
||||||
variant={'ghost'}
|
variant={'ghost'}
|
||||||
className="border border-border-button"
|
className="border border-border-button"
|
||||||
@ -460,53 +559,188 @@ export const ManageMetadataModal = (props: IManageModalProps) => {
|
|||||||
</Button>
|
</Button>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
<Table rootClassName="max-h-[800px]">
|
{metadataType === MetadataType.Setting ? (
|
||||||
<TableHeader>
|
<Tabs
|
||||||
{table.getHeaderGroups().map((headerGroup) => (
|
value={activeTab}
|
||||||
<TableRow key={headerGroup.id}>
|
onValueChange={(v) => setActiveTab(v as MetadataSettingsTab)}
|
||||||
{headerGroup.headers.map((header) => (
|
>
|
||||||
<TableHead key={header.id}>
|
<TabsList className="w-fit">
|
||||||
{header.isPlaceholder
|
<TabsTrigger value="generation">Generation</TabsTrigger>
|
||||||
? null
|
<TabsTrigger value="built-in">
|
||||||
: flexRender(
|
{t('knowledgeConfiguration.builtIn')}
|
||||||
header.column.columnDef.header,
|
</TabsTrigger>
|
||||||
header.getContext(),
|
</TabsList>
|
||||||
)}
|
<TabsContent value="generation">
|
||||||
</TableHead>
|
<Table rootClassName="max-h-[800px]">
|
||||||
))}
|
<TableHeader>
|
||||||
</TableRow>
|
{table.getHeaderGroups().map((headerGroup) => (
|
||||||
))}
|
<TableRow key={headerGroup.id}>
|
||||||
</TableHeader>
|
{headerGroup.headers.map((header) => (
|
||||||
<TableBody className="relative">
|
<TableHead key={header.id}>
|
||||||
{table.getRowModel().rows?.length ? (
|
{header.isPlaceholder
|
||||||
table.getRowModel().rows.map((row) => (
|
? null
|
||||||
<TableRow
|
: flexRender(
|
||||||
key={row.id}
|
header.column.columnDef.header,
|
||||||
data-state={row.getIsSelected() && 'selected'}
|
header.getContext(),
|
||||||
className="group"
|
)}
|
||||||
>
|
</TableHead>
|
||||||
{row.getVisibleCells().map((cell) => (
|
))}
|
||||||
<TableCell key={cell.id}>
|
</TableRow>
|
||||||
{flexRender(
|
))}
|
||||||
cell.column.columnDef.cell,
|
</TableHeader>
|
||||||
cell.getContext(),
|
<TableBody className="relative">
|
||||||
)}
|
{table.getRowModel().rows?.length ? (
|
||||||
</TableCell>
|
table.getRowModel().rows.map((row) => (
|
||||||
|
<TableRow
|
||||||
|
key={row.id}
|
||||||
|
data-state={row.getIsSelected() && 'selected'}
|
||||||
|
className="group"
|
||||||
|
>
|
||||||
|
{row.getVisibleCells().map((cell) => (
|
||||||
|
<TableCell key={cell.id}>
|
||||||
|
{flexRender(
|
||||||
|
cell.column.columnDef.cell,
|
||||||
|
cell.getContext(),
|
||||||
|
)}
|
||||||
|
</TableCell>
|
||||||
|
))}
|
||||||
|
</TableRow>
|
||||||
|
))
|
||||||
|
) : (
|
||||||
|
<TableRow>
|
||||||
|
<TableCell
|
||||||
|
colSpan={columns.length}
|
||||||
|
className="h-24 text-center"
|
||||||
|
>
|
||||||
|
<Empty type={EmptyType.Data} />
|
||||||
|
</TableCell>
|
||||||
|
</TableRow>
|
||||||
|
)}
|
||||||
|
</TableBody>
|
||||||
|
</Table>
|
||||||
|
</TabsContent>
|
||||||
|
<TabsContent value="built-in">
|
||||||
|
<Table rootClassName="max-h-[800px]">
|
||||||
|
<TableHeader>
|
||||||
|
<TableRow>
|
||||||
|
<TableHead>
|
||||||
|
{t('knowledgeDetails.metadata.field')}
|
||||||
|
</TableHead>
|
||||||
|
<TableHead>Type</TableHead>
|
||||||
|
<TableHead>
|
||||||
|
{t('knowledgeDetails.metadata.description')}
|
||||||
|
</TableHead>
|
||||||
|
<TableHead className="text-right">
|
||||||
|
{t('knowledgeDetails.metadata.action')}
|
||||||
|
</TableHead>
|
||||||
|
</TableRow>
|
||||||
|
</TableHeader>
|
||||||
|
<TableBody className="relative">
|
||||||
|
{builtInRows.map((row) => (
|
||||||
|
<TableRow key={row.field}>
|
||||||
|
<TableCell>
|
||||||
|
<div className="text-sm text-accent-primary">
|
||||||
|
{row.field}
|
||||||
|
</div>
|
||||||
|
</TableCell>
|
||||||
|
<TableCell>
|
||||||
|
<div className="text-sm">
|
||||||
|
{getMetadataValueTypeLabel(
|
||||||
|
row.valueType as IMetaDataTableData['valueType'],
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
</TableCell>
|
||||||
|
<TableCell>
|
||||||
|
<div className="text-sm truncate max-w-32">
|
||||||
|
{row.description}
|
||||||
|
</div>
|
||||||
|
</TableCell>
|
||||||
|
<TableCell className="text-right">
|
||||||
|
<Switch
|
||||||
|
checked={builtInSelectionKeys.has(row.field)}
|
||||||
|
onCheckedChange={(checked) => {
|
||||||
|
setBuiltInSelection((prev) => {
|
||||||
|
if (checked) {
|
||||||
|
const nextType =
|
||||||
|
row.valueType as IBuiltInMetadataItem['type'];
|
||||||
|
if (
|
||||||
|
prev.some(
|
||||||
|
(item) => item.key === row.field,
|
||||||
|
)
|
||||||
|
) {
|
||||||
|
return prev.map((item) =>
|
||||||
|
item.key === row.field
|
||||||
|
? { ...item, type: nextType }
|
||||||
|
: item,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
return [
|
||||||
|
...prev,
|
||||||
|
{ key: row.field, type: nextType },
|
||||||
|
];
|
||||||
|
}
|
||||||
|
return prev.filter(
|
||||||
|
(item) => item.key !== row.field,
|
||||||
|
);
|
||||||
|
});
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</TableCell>
|
||||||
|
</TableRow>
|
||||||
|
))}
|
||||||
|
</TableBody>
|
||||||
|
</Table>
|
||||||
|
</TabsContent>
|
||||||
|
</Tabs>
|
||||||
|
) : (
|
||||||
|
<Table rootClassName="max-h-[800px]">
|
||||||
|
<TableHeader>
|
||||||
|
{table.getHeaderGroups().map((headerGroup) => (
|
||||||
|
<TableRow key={headerGroup.id}>
|
||||||
|
{headerGroup.headers.map((header) => (
|
||||||
|
<TableHead key={header.id}>
|
||||||
|
{header.isPlaceholder
|
||||||
|
? null
|
||||||
|
: flexRender(
|
||||||
|
header.column.columnDef.header,
|
||||||
|
header.getContext(),
|
||||||
|
)}
|
||||||
|
</TableHead>
|
||||||
))}
|
))}
|
||||||
</TableRow>
|
</TableRow>
|
||||||
))
|
))}
|
||||||
) : (
|
</TableHeader>
|
||||||
<TableRow>
|
<TableBody className="relative">
|
||||||
<TableCell
|
{table.getRowModel().rows?.length ? (
|
||||||
colSpan={columns.length}
|
table.getRowModel().rows.map((row) => (
|
||||||
className="h-24 text-center"
|
<TableRow
|
||||||
>
|
key={row.id}
|
||||||
<Empty type={EmptyType.Data} />
|
data-state={row.getIsSelected() && 'selected'}
|
||||||
</TableCell>
|
className="group"
|
||||||
</TableRow>
|
>
|
||||||
)}
|
{row.getVisibleCells().map((cell) => (
|
||||||
</TableBody>
|
<TableCell key={cell.id}>
|
||||||
</Table>
|
{flexRender(
|
||||||
|
cell.column.columnDef.cell,
|
||||||
|
cell.getContext(),
|
||||||
|
)}
|
||||||
|
</TableCell>
|
||||||
|
))}
|
||||||
|
</TableRow>
|
||||||
|
))
|
||||||
|
) : (
|
||||||
|
<TableRow>
|
||||||
|
<TableCell
|
||||||
|
colSpan={columns.length}
|
||||||
|
className="h-24 text-center"
|
||||||
|
>
|
||||||
|
<Empty type={EmptyType.Data} />
|
||||||
|
</TableCell>
|
||||||
|
</TableRow>
|
||||||
|
)}
|
||||||
|
</TableBody>
|
||||||
|
</Table>
|
||||||
|
)}
|
||||||
</div>
|
</div>
|
||||||
{metadataType === MetadataType.Manage && (
|
{metadataType === MetadataType.Manage && (
|
||||||
<div className=" absolute bottom-6 left-5 text-text-secondary text-sm">
|
<div className=" absolute bottom-6 left-5 text-text-secondary text-sm">
|
||||||
@ -537,6 +771,7 @@ export const ManageMetadataModal = (props: IManageModalProps) => {
|
|||||||
isAddValue={isAddValue || isCanAdd}
|
isAddValue={isAddValue || isCanAdd}
|
||||||
isShowDescription={isShowDescription}
|
isShowDescription={isShowDescription}
|
||||||
isShowValueSwitch={isShowValueSwitch}
|
isShowValueSwitch={isShowValueSwitch}
|
||||||
|
isShowType={isSettingsMode}
|
||||||
isVerticalShowValue={isVerticalShowValue}
|
isVerticalShowValue={isVerticalShowValue}
|
||||||
// handleDeleteSingleValue={handleDeleteSingleValue}
|
// handleDeleteSingleValue={handleDeleteSingleValue}
|
||||||
// handleDeleteSingleRow={handleDeleteSingleRow}
|
// handleDeleteSingleRow={handleDeleteSingleRow}
|
||||||
|
|||||||
@ -7,11 +7,15 @@ import { Button } from '@/components/ui/button';
|
|||||||
import { FormLabel } from '@/components/ui/form';
|
import { FormLabel } from '@/components/ui/form';
|
||||||
import { Input } from '@/components/ui/input';
|
import { Input } from '@/components/ui/input';
|
||||||
import { Modal } from '@/components/ui/modal/modal';
|
import { Modal } from '@/components/ui/modal/modal';
|
||||||
import { Switch } from '@/components/ui/switch';
|
import { RAGFlowSelect } from '@/components/ui/select';
|
||||||
import { Textarea } from '@/components/ui/textarea';
|
import { Textarea } from '@/components/ui/textarea';
|
||||||
import { Plus, Trash2 } from 'lucide-react';
|
import { Plus, Trash2 } from 'lucide-react';
|
||||||
import { memo } from 'react';
|
import { memo } from 'react';
|
||||||
import { useTranslation } from 'react-i18next';
|
import { useTranslation } from 'react-i18next';
|
||||||
|
import {
|
||||||
|
isMetadataValueTypeWithEnum,
|
||||||
|
metadataValueTypeOptions,
|
||||||
|
} from './hooks/use-manage-modal';
|
||||||
import { useManageValues } from './hooks/use-manage-values-modal';
|
import { useManageValues } from './hooks/use-manage-values-modal';
|
||||||
import { IManageValuesProps } from './interface';
|
import { IManageValuesProps } from './interface';
|
||||||
|
|
||||||
@ -62,8 +66,8 @@ export const ManageValuesModal = (props: IManageValuesProps) => {
|
|||||||
visible,
|
visible,
|
||||||
isAddValue,
|
isAddValue,
|
||||||
isShowDescription,
|
isShowDescription,
|
||||||
isShowValueSwitch,
|
|
||||||
isVerticalShowValue,
|
isVerticalShowValue,
|
||||||
|
isShowType,
|
||||||
} = props;
|
} = props;
|
||||||
const {
|
const {
|
||||||
metaData,
|
metaData,
|
||||||
@ -80,6 +84,7 @@ export const ManageValuesModal = (props: IManageValuesProps) => {
|
|||||||
handleHideModal,
|
handleHideModal,
|
||||||
} = useManageValues(props);
|
} = useManageValues(props);
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
|
const canShowValues = isMetadataValueTypeWithEnum(metaData.valueType);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Modal
|
<Modal
|
||||||
@ -115,6 +120,16 @@ export const ManageValuesModal = (props: IManageValuesProps) => {
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
|
{isShowType && (
|
||||||
|
<div className="flex flex-col gap-2">
|
||||||
|
<div>Type</div>
|
||||||
|
<RAGFlowSelect
|
||||||
|
value={metaData.valueType || 'string'}
|
||||||
|
options={metadataValueTypeOptions}
|
||||||
|
onChange={(value) => handleChange('valueType', value)}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
{isShowDescription && (
|
{isShowDescription && (
|
||||||
<div className="flex flex-col gap-2">
|
<div className="flex flex-col gap-2">
|
||||||
<FormLabel
|
<FormLabel
|
||||||
@ -133,26 +148,7 @@ export const ManageValuesModal = (props: IManageValuesProps) => {
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
{isShowValueSwitch && (
|
{canShowValues && (
|
||||||
<div className="flex flex-col gap-2">
|
|
||||||
<FormLabel
|
|
||||||
className="text-text-primary text-base"
|
|
||||||
tooltip={t('knowledgeDetails.metadata.restrictTDefinedValuesTip')}
|
|
||||||
>
|
|
||||||
{t('knowledgeDetails.metadata.restrictDefinedValues')}
|
|
||||||
</FormLabel>
|
|
||||||
<div>
|
|
||||||
<Switch
|
|
||||||
checked={metaData.restrictDefinedValues || false}
|
|
||||||
onCheckedChange={(checked) =>
|
|
||||||
handleChange('restrictDefinedValues', checked)
|
|
||||||
}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
)}
|
|
||||||
{((metaData.restrictDefinedValues && isShowValueSwitch) ||
|
|
||||||
!isShowValueSwitch) && (
|
|
||||||
<div className="flex flex-col gap-2">
|
<div className="flex flex-col gap-2">
|
||||||
<div className="flex justify-between items-center">
|
<div className="flex justify-between items-center">
|
||||||
<div>{t('knowledgeDetails.metadata.values')}</div>
|
<div>{t('knowledgeDetails.metadata.values')}</div>
|
||||||
|
|||||||
@ -39,7 +39,10 @@ import {
|
|||||||
useManageMetadata,
|
useManageMetadata,
|
||||||
util,
|
util,
|
||||||
} from '../../components/metedata/hooks/use-manage-modal';
|
} from '../../components/metedata/hooks/use-manage-modal';
|
||||||
import { IMetaDataReturnJSONSettings } from '../../components/metedata/interface';
|
import {
|
||||||
|
IBuiltInMetadataItem,
|
||||||
|
IMetaDataReturnJSONSettings,
|
||||||
|
} from '../../components/metedata/interface';
|
||||||
import { ManageMetadataModal } from '../../components/metedata/manage-modal';
|
import { ManageMetadataModal } from '../../components/metedata/manage-modal';
|
||||||
import {
|
import {
|
||||||
useHandleKbEmbedding,
|
useHandleKbEmbedding,
|
||||||
@ -384,12 +387,14 @@ export function AutoMetadata({
|
|||||||
|
|
||||||
const handleClickOpenMetadata = useCallback(() => {
|
const handleClickOpenMetadata = useCallback(() => {
|
||||||
const metadata = form.getValues('parser_config.metadata');
|
const metadata = form.getValues('parser_config.metadata');
|
||||||
|
const builtInMetadata = form.getValues('parser_config.built_in_metadata');
|
||||||
const tableMetaData = util.metaDataSettingJSONToMetaDataTableData(metadata);
|
const tableMetaData = util.metaDataSettingJSONToMetaDataTableData(metadata);
|
||||||
showManageMetadataModal({
|
showManageMetadataModal({
|
||||||
metadata: tableMetaData,
|
metadata: tableMetaData,
|
||||||
isCanAdd: true,
|
isCanAdd: true,
|
||||||
type: type,
|
type: type,
|
||||||
record: otherData,
|
record: otherData,
|
||||||
|
builtInMetadata,
|
||||||
});
|
});
|
||||||
}, [form, otherData, showManageMetadataModal, type]);
|
}, [form, otherData, showManageMetadataModal, type]);
|
||||||
|
|
||||||
@ -429,8 +434,15 @@ export function AutoMetadata({
|
|||||||
),
|
),
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleSaveMetadata = (data?: IMetaDataReturnJSONSettings) => {
|
const handleSaveMetadata = (data?: {
|
||||||
form.setValue('parser_config.metadata', data || []);
|
metadata?: IMetaDataReturnJSONSettings;
|
||||||
|
builtInMetadata?: IBuiltInMetadataItem[];
|
||||||
|
}) => {
|
||||||
|
form.setValue('parser_config.metadata', data?.metadata || []);
|
||||||
|
form.setValue(
|
||||||
|
'parser_config.built_in_metadata',
|
||||||
|
data?.builtInMetadata || [],
|
||||||
|
);
|
||||||
form.setValue('parser_config.enable_metadata', true);
|
form.setValue('parser_config.enable_metadata', true);
|
||||||
};
|
};
|
||||||
return (
|
return (
|
||||||
@ -461,7 +473,11 @@ export function AutoMetadata({
|
|||||||
isShowDescription={true}
|
isShowDescription={true}
|
||||||
isShowValueSwitch={true}
|
isShowValueSwitch={true}
|
||||||
isVerticalShowValue={false}
|
isVerticalShowValue={false}
|
||||||
success={(data?: IMetaDataReturnJSONSettings) => {
|
builtInMetadata={metadataConfig.builtInMetadata}
|
||||||
|
success={(data?: {
|
||||||
|
metadata?: IMetaDataReturnJSONSettings;
|
||||||
|
builtInMetadata?: IBuiltInMetadataItem[];
|
||||||
|
}) => {
|
||||||
handleSaveMetadata(data);
|
handleSaveMetadata(data);
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
|
|||||||
@ -84,15 +84,13 @@ export const formSchema = z
|
|||||||
path: ['entity_types'],
|
path: ['entity_types'],
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
metadata: z
|
metadata: z.any().optional(),
|
||||||
|
built_in_metadata: z
|
||||||
.array(
|
.array(
|
||||||
z
|
z.object({
|
||||||
.object({
|
key: z.string().optional(),
|
||||||
key: z.string().optional(),
|
type: z.string().optional(),
|
||||||
description: z.string().optional(),
|
}),
|
||||||
enum: z.array(z.string().optional()).optional(),
|
|
||||||
})
|
|
||||||
.optional(),
|
|
||||||
)
|
)
|
||||||
.optional(),
|
.optional(),
|
||||||
enable_metadata: z.boolean().optional(),
|
enable_metadata: z.boolean().optional(),
|
||||||
|
|||||||
@ -95,7 +95,12 @@ export default function DatasetSettings() {
|
|||||||
entity_types: initialEntityTypes,
|
entity_types: initialEntityTypes,
|
||||||
method: MethodValue.Light,
|
method: MethodValue.Light,
|
||||||
},
|
},
|
||||||
metadata: [],
|
metadata: {
|
||||||
|
type: 'object',
|
||||||
|
properties: {},
|
||||||
|
additionalProperties: false,
|
||||||
|
},
|
||||||
|
built_in_metadata: [],
|
||||||
enable_metadata: false,
|
enable_metadata: false,
|
||||||
llm_id: '',
|
llm_id: '',
|
||||||
},
|
},
|
||||||
|
|||||||
Reference in New Issue
Block a user