mirror of
https://github.com/infiniflow/ragflow.git
synced 2025-12-23 06:46:40 +08:00
Fix: Bug fixes (#11960)
### What problem does this PR solve? Fix: Bug fixes New search popup style modification Fixed multilingual settings not updating immediately on personal center page Changed overlapped percent to percentage format, with maximum value of 30% ### Type of change - [x] Bug Fix (non-breaking change which fixes an issue)
This commit is contained in:
@ -11,6 +11,7 @@ import {
|
||||
DefaultValues,
|
||||
FieldValues,
|
||||
SubmitHandler,
|
||||
UseFormTrigger,
|
||||
useForm,
|
||||
useFormContext,
|
||||
} from 'react-hook-form';
|
||||
@ -99,8 +100,9 @@ interface DynamicFormProps<T extends FieldValues> {
|
||||
// Form ref interface
|
||||
export interface DynamicFormRef {
|
||||
submit: () => void;
|
||||
getValues: () => any;
|
||||
getValues: (name?: string) => any;
|
||||
reset: (values?: any) => void;
|
||||
trigger: UseFormTrigger<any>;
|
||||
watch: (field: string, callback: (value: any) => void) => () => void;
|
||||
updateFieldType: (fieldName: string, newType: FormFieldType) => void;
|
||||
onFieldUpdate: (
|
||||
@ -704,8 +706,8 @@ const DynamicForm = {
|
||||
useImperativeHandle(
|
||||
ref,
|
||||
() => ({
|
||||
submit: () => form.handleSubmit(onSubmit)(),
|
||||
getValues: () => form.getValues(),
|
||||
submit: form.handleSubmit,
|
||||
getValues: form.getValues,
|
||||
reset: (values?: T) => {
|
||||
if (values) {
|
||||
form.reset(values);
|
||||
|
||||
@ -26,6 +26,7 @@ type SliderInputFormFieldProps = {
|
||||
defaultValue?: number;
|
||||
className?: string;
|
||||
numberInputClassName?: string;
|
||||
percentage?: boolean;
|
||||
} & FormLayoutType;
|
||||
|
||||
export function SliderInputFormField({
|
||||
@ -39,11 +40,14 @@ export function SliderInputFormField({
|
||||
className,
|
||||
numberInputClassName,
|
||||
layout = FormLayout.Horizontal,
|
||||
percentage = false,
|
||||
}: SliderInputFormFieldProps) {
|
||||
const form = useFormContext();
|
||||
|
||||
const isHorizontal = useMemo(() => layout !== FormLayout.Vertical, [layout]);
|
||||
|
||||
const displayMax = percentage ? (max || 1) * 100 : max;
|
||||
const displayMin = percentage ? (min || 0) * 100 : min;
|
||||
const displayStep = percentage ? (step || 0.01) * 100 : step;
|
||||
return (
|
||||
<FormField
|
||||
control={form.control}
|
||||
@ -71,12 +75,13 @@ export function SliderInputFormField({
|
||||
<FormControl>
|
||||
<SingleFormSlider
|
||||
{...field}
|
||||
max={max}
|
||||
min={min}
|
||||
step={step}
|
||||
// defaultValue={
|
||||
// typeof defaultValue === 'number' ? [defaultValue] : undefined
|
||||
// }
|
||||
value={percentage ? field.value * 100 : field.value}
|
||||
onChange={(value) =>
|
||||
field.onChange(percentage ? value / 100 : value)
|
||||
}
|
||||
max={displayMax}
|
||||
min={displayMin}
|
||||
step={displayStep}
|
||||
></SingleFormSlider>
|
||||
</FormControl>
|
||||
<FormControl>
|
||||
@ -86,11 +91,20 @@ export function SliderInputFormField({
|
||||
'[appearance:textfield] [&::-webkit-outer-spin-button]:appearance-none [&::-webkit-inner-spin-button]:appearance-none',
|
||||
numberInputClassName,
|
||||
)}
|
||||
max={max}
|
||||
min={min}
|
||||
step={step}
|
||||
{...field}
|
||||
// defaultValue={defaultValue}
|
||||
max={displayMax}
|
||||
min={displayMin}
|
||||
step={displayStep}
|
||||
value={
|
||||
percentage ? (field.value * 100).toFixed(0) : field.value
|
||||
}
|
||||
onChange={(val) => {
|
||||
const value = Number(val || 0);
|
||||
if (!isNaN(value)) {
|
||||
field.onChange(
|
||||
percentage ? (value / 100).toFixed(0) : value,
|
||||
);
|
||||
}
|
||||
}}
|
||||
></NumberInput>
|
||||
</FormControl>
|
||||
</div>
|
||||
|
||||
@ -174,20 +174,23 @@ const Modal: ModalType = ({
|
||||
onClick={() => maskClosable && onOpenChange?.(false)}
|
||||
>
|
||||
<DialogPrimitive.Content
|
||||
className={`relative w-[700px] ${full ? 'max-w-full' : sizeClasses[size]} ${className} bg-bg-base rounded-lg shadow-lg border border-border-default transition-all focus-visible:!outline-none`}
|
||||
className={cn(
|
||||
`relative w-[700px] ${full ? 'max-w-full' : sizeClasses[size]} ${className} bg-bg-base rounded-lg shadow-lg border border-border-default transition-all focus-visible:!outline-none`,
|
||||
{ 'pt-10': closable && !title },
|
||||
)}
|
||||
style={style}
|
||||
onClick={(e) => e.stopPropagation()}
|
||||
>
|
||||
{/* title */}
|
||||
{(title || closable) && (
|
||||
{title && (
|
||||
<div
|
||||
className={cn(
|
||||
'flex items-start px-6 py-4',
|
||||
{
|
||||
'justify-end': closable && !title,
|
||||
'justify-between': closable && title,
|
||||
'justify-start': !closable,
|
||||
},
|
||||
'flex items-start px-6 py-4 justify-start',
|
||||
// {
|
||||
// 'justify-end': closable && !title,
|
||||
// 'justify-between': closable && title,
|
||||
// 'justify-start': !closable,
|
||||
// },
|
||||
titleClassName,
|
||||
)}
|
||||
>
|
||||
@ -196,19 +199,19 @@ const Modal: ModalType = ({
|
||||
{title}
|
||||
</DialogPrimitive.Title>
|
||||
)}
|
||||
</div>
|
||||
)}
|
||||
{closable && (
|
||||
<DialogPrimitive.Close asChild>
|
||||
<button
|
||||
type="button"
|
||||
className="flex h-7 w-7 items-center justify-center text-text-secondary rounded-full hover:text-text-primary focus-visible:outline-none"
|
||||
className="flex absolute right-5 top-5 h-7 w-7 items-center justify-center text-text-secondary rounded-full hover:text-text-primary focus-visible:outline-none"
|
||||
onClick={handleCancel}
|
||||
>
|
||||
{closeIcon}
|
||||
</button>
|
||||
</DialogPrimitive.Close>
|
||||
)}
|
||||
</div>
|
||||
)}
|
||||
|
||||
{/* content */}
|
||||
<div className="py-2 px-6 overflow-y-auto scrollbar-auto max-h-[calc(100vh-280px)] focus-visible:!outline-none">
|
||||
|
||||
@ -159,6 +159,7 @@ export default {
|
||||
doc: 'Docs',
|
||||
searchKnowledgePlaceholder: 'Search',
|
||||
noMoreData: `That's all. Nothing more.`,
|
||||
parserRequired: 'Chunk method is required',
|
||||
},
|
||||
knowledgeDetails: {
|
||||
localUpload: 'Local upload',
|
||||
@ -329,7 +330,7 @@ export default {
|
||||
reRankModelWaring: 'Re-rank model is very time consuming.',
|
||||
},
|
||||
knowledgeConfiguration: {
|
||||
overlappedPercent: 'Overlapped percent',
|
||||
overlappedPercent: 'Overlapped percent(%)',
|
||||
generationScopeTip:
|
||||
'Determines whether RAPTOR is generated for the entire dataset or for a single file.',
|
||||
scopeDataset: 'Dataset',
|
||||
|
||||
@ -101,6 +101,7 @@ export default {
|
||||
doc: '文档',
|
||||
searchKnowledgePlaceholder: '搜索',
|
||||
noMoreData: '没有更多数据了',
|
||||
parserRequired: '分块方法必填',
|
||||
},
|
||||
knowledgeDetails: {
|
||||
localUpload: '本地上传',
|
||||
|
||||
@ -24,7 +24,8 @@ import { useNavigatePage } from '@/hooks/logic-hooks/navigate-hooks';
|
||||
import { cn } from '@/lib/utils';
|
||||
import { PipelineResultSearchParams } from '@/pages/dataflow-result/constant';
|
||||
import { NavigateToDataflowResultProps } from '@/pages/dataflow-result/interface';
|
||||
import { DataSourceInfo } from '@/pages/user-setting/data-source/contant';
|
||||
import { useDataSourceInfo } from '@/pages/user-setting/data-source/contant';
|
||||
import { IDataSourceInfoMap } from '@/pages/user-setting/data-source/interface';
|
||||
import { formatDate, formatSecondsToHumanReadable } from '@/utils/date';
|
||||
import {
|
||||
ColumnDef,
|
||||
@ -54,6 +55,7 @@ export const getFileLogsTableColumns = (
|
||||
navigateToDataflowResult: (
|
||||
props: NavigateToDataflowResultProps,
|
||||
) => () => void,
|
||||
dataSourceInfo: IDataSourceInfoMap,
|
||||
) => {
|
||||
// const { t } = useTranslate('knowledgeDetails');
|
||||
const columns: ColumnDef<IFileLogItem & DocumentLog>[] = [
|
||||
@ -117,8 +119,8 @@ export const getFileLogsTableColumns = (
|
||||
) : (
|
||||
<div className="w-6 h-6 flex items-center justify-center">
|
||||
{
|
||||
DataSourceInfo[
|
||||
row.original.source_from as keyof typeof DataSourceInfo
|
||||
dataSourceInfo[
|
||||
row.original.source_from as keyof typeof dataSourceInfo
|
||||
].icon
|
||||
}
|
||||
</div>
|
||||
@ -368,7 +370,7 @@ const FileLogsTable: FC<FileLogsTableProps> = ({
|
||||
setLogInfo(logDetail);
|
||||
setIsModalVisible(true);
|
||||
};
|
||||
|
||||
const { dataSourceInfo } = useDataSourceInfo();
|
||||
const columns = useMemo(() => {
|
||||
return active === LogTabs.FILE_LOGS
|
||||
? getFileLogsTableColumns(
|
||||
@ -376,6 +378,7 @@ const FileLogsTable: FC<FileLogsTableProps> = ({
|
||||
showLog,
|
||||
kowledgeId || '',
|
||||
navigateToDataflowResult,
|
||||
dataSourceInfo,
|
||||
)
|
||||
: getDatasetLogsTableColumns(t, showLog);
|
||||
}, [active, t]);
|
||||
|
||||
@ -9,7 +9,7 @@ import {
|
||||
import { useNavigatePage } from '@/hooks/logic-hooks/navigate-hooks';
|
||||
import { IConnector } from '@/interfaces/database/knowledge';
|
||||
import { delSourceModal } from '@/pages/user-setting/data-source/component/delete-source-modal';
|
||||
import { DataSourceInfo } from '@/pages/user-setting/data-source/contant';
|
||||
import { useDataSourceInfo } from '@/pages/user-setting/data-source/contant';
|
||||
import { useDataSourceRebuild } from '@/pages/user-setting/data-source/hooks';
|
||||
import { IDataSourceBase } from '@/pages/user-setting/data-source/interface';
|
||||
import { Link, Settings, Unlink } from 'lucide-react';
|
||||
@ -41,6 +41,7 @@ interface DataSourceItemProps extends IDataSourceNodeProps {
|
||||
}
|
||||
|
||||
const DataSourceItem = (props: DataSourceItemProps) => {
|
||||
const { dataSourceInfo } = useDataSourceInfo();
|
||||
const { t } = useTranslation();
|
||||
const { id, name, icon, source, auto_parse, unbindFunc, handleAutoParse } =
|
||||
props;
|
||||
@ -56,7 +57,7 @@ const DataSourceItem = (props: DataSourceItemProps) => {
|
||||
<div className="flex items-center gap-1">
|
||||
<div className="w-6 h-6 flex-shrink-0">{icon}</div>
|
||||
<div className="text-base text-text-primary">
|
||||
{DataSourceInfo[source].name}
|
||||
{dataSourceInfo[source].name}
|
||||
</div>
|
||||
<div>{name}</div>
|
||||
</div>
|
||||
@ -114,6 +115,7 @@ const DataSourceItem = (props: DataSourceItemProps) => {
|
||||
delSourceModal({
|
||||
data: props,
|
||||
type: 'unlink',
|
||||
dataSourceInfo: dataSourceInfo,
|
||||
onOk: (data) => unbindFunc?.(data as DataSourceItemProps),
|
||||
});
|
||||
}}
|
||||
@ -134,6 +136,7 @@ const LinkDataSource = (props: ILinkDataSourceProps) => {
|
||||
handleAutoParse,
|
||||
} = props;
|
||||
const { t } = useTranslation();
|
||||
const { dataSourceInfo } = useDataSourceInfo();
|
||||
const [openLinkModal, setOpenLinkModal] = useState(false);
|
||||
|
||||
const pipelineNode: IDataSourceNodeProps[] = useMemo(() => {
|
||||
@ -144,7 +147,7 @@ const LinkDataSource = (props: ILinkDataSourceProps) => {
|
||||
id: item?.id,
|
||||
name: item?.name,
|
||||
icon:
|
||||
DataSourceInfo[item?.source as keyof typeof DataSourceInfo]?.icon ||
|
||||
dataSourceInfo[item?.source as keyof typeof dataSourceInfo]?.icon ||
|
||||
'',
|
||||
} as IDataSourceNodeProps;
|
||||
});
|
||||
|
||||
@ -291,9 +291,10 @@ export function EnableTocToggle() {
|
||||
export function OverlappedPercent() {
|
||||
return (
|
||||
<SliderInputFormField
|
||||
percentage={true}
|
||||
name="parser_config.overlapped_percent"
|
||||
label={t('knowledgeConfiguration.overlappedPercent')}
|
||||
max={0.5}
|
||||
max={0.3}
|
||||
step={0.01}
|
||||
></SliderInputFormField>
|
||||
);
|
||||
|
||||
@ -8,7 +8,7 @@ import { FormLayout } from '@/constants/form';
|
||||
import { DocumentParserType } from '@/constants/knowledge';
|
||||
import { PermissionRole } from '@/constants/permission';
|
||||
import { IConnector } from '@/interfaces/database/knowledge';
|
||||
import { DataSourceInfo } from '@/pages/user-setting/data-source/contant';
|
||||
import { useDataSourceInfo } from '@/pages/user-setting/data-source/contant';
|
||||
import { IDataSourceBase } from '@/pages/user-setting/data-source/interface';
|
||||
import { zodResolver } from '@hookform/resolvers/zod';
|
||||
import { useEffect, useState } from 'react';
|
||||
@ -89,6 +89,7 @@ export default function DatasetSettings() {
|
||||
connectors: [],
|
||||
},
|
||||
});
|
||||
const { dataSourceInfo } = useDataSourceInfo();
|
||||
const knowledgeDetails = useFetchKnowledgeConfigurationOnMount(form);
|
||||
// const [pipelineData, setPipelineData] = useState<IDataPipelineNodeProps>();
|
||||
const [sourceData, setSourceData] = useState<IDataSourceNodeProps[]>();
|
||||
@ -113,7 +114,7 @@ export default function DatasetSettings() {
|
||||
return {
|
||||
...connector,
|
||||
icon:
|
||||
DataSourceInfo[connector.source as keyof typeof DataSourceInfo]
|
||||
dataSourceInfo[connector.source as keyof typeof dataSourceInfo]
|
||||
?.icon || '',
|
||||
};
|
||||
});
|
||||
@ -159,7 +160,7 @@ export default function DatasetSettings() {
|
||||
...connector,
|
||||
auto_parse: connector.auto_parse === '0' ? '0' : '1',
|
||||
icon:
|
||||
DataSourceInfo[connector.source as keyof typeof DataSourceInfo]
|
||||
dataSourceInfo[connector.source as keyof typeof dataSourceInfo]
|
||||
?.icon || '',
|
||||
};
|
||||
});
|
||||
|
||||
@ -11,7 +11,7 @@ import { useNavigatePage } from '@/hooks/logic-hooks/navigate-hooks';
|
||||
import { useSetDocumentStatus } from '@/hooks/use-document-request';
|
||||
import { IDocumentInfo } from '@/interfaces/database/document';
|
||||
import { cn } from '@/lib/utils';
|
||||
import { DataSourceInfo } from '@/pages/user-setting/data-source/contant';
|
||||
import { useDataSourceInfo } from '@/pages/user-setting/data-source/contant';
|
||||
import { formatDate } from '@/utils/date';
|
||||
import { ColumnDef } from '@tanstack/table-core';
|
||||
import { ArrowUpDown, MonitorUp } from 'lucide-react';
|
||||
@ -35,7 +35,7 @@ export function useDatasetTableColumns({
|
||||
const { t } = useTranslation('translation', {
|
||||
keyPrefix: 'knowledgeDetails',
|
||||
});
|
||||
|
||||
const { dataSourceInfo } = useDataSourceInfo();
|
||||
const { navigateToChunkParsedResult } = useNavigatePage();
|
||||
const { setDocumentStatus } = useSetDocumentStatus();
|
||||
|
||||
@ -134,8 +134,8 @@ export function useDatasetTableColumns({
|
||||
) : (
|
||||
<div className="w-6 h-6 flex items-center justify-center">
|
||||
{
|
||||
DataSourceInfo[
|
||||
row.original.source_type as keyof typeof DataSourceInfo
|
||||
dataSourceInfo[
|
||||
row.original.source_type as keyof typeof dataSourceInfo
|
||||
]?.icon
|
||||
}
|
||||
</div>
|
||||
|
||||
@ -1,7 +1,6 @@
|
||||
import { CardContainer } from '@/components/card-container';
|
||||
import { EmptyCardType } from '@/components/empty/constant';
|
||||
import { EmptyAppCard } from '@/components/empty/empty';
|
||||
import { IconFont } from '@/components/icon-font';
|
||||
import ListFilterBar from '@/components/list-filter-bar';
|
||||
import { RenameDialog } from '@/components/rename-dialog';
|
||||
import { Button } from '@/components/ui/button';
|
||||
@ -149,7 +148,7 @@ export default function SearchList() {
|
||||
onOk={onSearchRenameConfirm}
|
||||
initialName={initialSearchName}
|
||||
loading={searchRenameLoading}
|
||||
title={<IconFont name="search" className="size-6"></IconFont>}
|
||||
title={initialSearchName || t('createSearch')}
|
||||
></RenameDialog>
|
||||
)}
|
||||
</section>
|
||||
|
||||
@ -2,6 +2,7 @@ import { Button } from '@/components/ui/button';
|
||||
import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card';
|
||||
import { useNavigatePage } from '@/hooks/logic-hooks/navigate-hooks';
|
||||
import { Settings, Trash2 } from 'lucide-react';
|
||||
import { useDataSourceInfo } from '../contant';
|
||||
import { useDeleteDataSource } from '../hooks';
|
||||
import { IDataSorceInfo, IDataSourceBase } from '../interface';
|
||||
import { delSourceModal } from './delete-source-modal';
|
||||
@ -13,6 +14,7 @@ export const AddedSourceCard = (props: IAddedSourceCardProps) => {
|
||||
const { list, name, icon } = props;
|
||||
const { handleDelete } = useDeleteDataSource();
|
||||
const { navigateToDataSourceDetail } = useNavigatePage();
|
||||
const { dataSourceInfo } = useDataSourceInfo();
|
||||
const toDetail = (id: string) => {
|
||||
navigateToDataSourceDetail(id);
|
||||
};
|
||||
@ -49,6 +51,7 @@ export const AddedSourceCard = (props: IAddedSourceCardProps) => {
|
||||
onClick={() =>
|
||||
delSourceModal({
|
||||
data: item,
|
||||
dataSourceInfo: dataSourceInfo,
|
||||
onOk: () => {
|
||||
handleDelete(item);
|
||||
},
|
||||
|
||||
@ -1,20 +1,19 @@
|
||||
import { Button } from '@/components/ui/button';
|
||||
import { Modal, ModalType } from '@/components/ui/modal/modal';
|
||||
import { t } from 'i18next';
|
||||
import { DataSourceInfo } from '../contant';
|
||||
import { IDataSourceBase } from '../interface';
|
||||
import { IDataSourceBase, IDataSourceInfoMap } from '../interface';
|
||||
|
||||
export type IDelSourceModalProps<T> = Partial<ModalType> & {
|
||||
data?: T;
|
||||
type?: 'delete' | 'unlink';
|
||||
onOk?: (data?: T) => void;
|
||||
dataSourceInfo: IDataSourceInfoMap;
|
||||
};
|
||||
|
||||
export const delSourceModal = <T extends IDataSourceBase>(
|
||||
props: IDelSourceModalProps<T>,
|
||||
) => {
|
||||
const { data, onOk, type = 'delete', ...otherProps } = props;
|
||||
console.log('data', data);
|
||||
const { data, onOk, type = 'delete', dataSourceInfo, ...otherProps } = props;
|
||||
const config = {
|
||||
title:
|
||||
type === 'delete'
|
||||
@ -39,7 +38,7 @@ export const delSourceModal = <T extends IDataSourceBase>(
|
||||
)}
|
||||
<div className="flex items-center gap-1 p-2 border border-border-button rounded-md mb-3">
|
||||
<div className="w-6 h-6 flex-shrink-0">
|
||||
{data?.source ? DataSourceInfo[data?.source].icon : ''}
|
||||
{data?.source ? dataSourceInfo[data?.source].icon : ''}
|
||||
</div>
|
||||
<div className="flex items-center gap-2 text-text-secondary text-xs">
|
||||
{/* <div className="h-6 flex-shrink-0 text-text-primary text-base">
|
||||
|
||||
@ -1,11 +1,13 @@
|
||||
import { FormFieldType } from '@/components/dynamic-form';
|
||||
import SvgIcon from '@/components/svg-icon';
|
||||
import { t } from 'i18next';
|
||||
import { t, TFunction } from 'i18next';
|
||||
import { useEffect, useState } from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import BoxTokenField from './component/box-token-field';
|
||||
import { ConfluenceIndexingModeField } from './component/confluence-token-field';
|
||||
import GmailTokenField from './component/gmail-token-field';
|
||||
import GoogleDriveTokenField from './component/google-drive-token-field';
|
||||
|
||||
import { IDataSourceInfoMap } from './interface';
|
||||
export enum DataSourceKey {
|
||||
CONFLUENCE = 'confluence',
|
||||
S3 = 's3',
|
||||
@ -23,7 +25,8 @@ export enum DataSourceKey {
|
||||
// TEAMS = 'teams',
|
||||
}
|
||||
|
||||
export const DataSourceInfo = {
|
||||
export const generateDataSourceInfo = (t: TFunction) => {
|
||||
return {
|
||||
[DataSourceKey.S3]: {
|
||||
name: 'S3',
|
||||
description: t(`setting.${DataSourceKey.S3}Description`),
|
||||
@ -79,6 +82,18 @@ export const DataSourceInfo = {
|
||||
description: t(`setting.${DataSourceKey.BOX}Description`),
|
||||
icon: <SvgIcon name={'data-source/box'} width={38} />,
|
||||
},
|
||||
};
|
||||
};
|
||||
|
||||
export const useDataSourceInfo = () => {
|
||||
const { t } = useTranslation();
|
||||
const [dataSourceInfo, setDataSourceInfo] = useState<IDataSourceInfoMap>(
|
||||
generateDataSourceInfo(t) as IDataSourceInfoMap,
|
||||
);
|
||||
useEffect(() => {
|
||||
setDataSourceInfo(generateDataSourceInfo(t));
|
||||
}, [t]);
|
||||
return { dataSourceInfo };
|
||||
};
|
||||
|
||||
export const DataSourceFormBaseFields = [
|
||||
|
||||
@ -18,7 +18,7 @@ import {
|
||||
DataSourceFormBaseFields,
|
||||
DataSourceFormDefaultValues,
|
||||
DataSourceFormFields,
|
||||
DataSourceInfo,
|
||||
useDataSourceInfo,
|
||||
} from '../contant';
|
||||
import {
|
||||
useAddDataSource,
|
||||
@ -32,10 +32,10 @@ const SourceDetailPage = () => {
|
||||
|
||||
const { data: detail } = useFetchDataSourceDetail();
|
||||
const { handleResume } = useDataSourceResume();
|
||||
|
||||
const { dataSourceInfo } = useDataSourceInfo();
|
||||
const detailInfo = useMemo(() => {
|
||||
if (detail) {
|
||||
return DataSourceInfo[detail.source];
|
||||
return dataSourceInfo[detail.source];
|
||||
}
|
||||
}, [detail]);
|
||||
|
||||
|
||||
@ -12,10 +12,11 @@ import { useQuery, useQueryClient } from '@tanstack/react-query';
|
||||
import { t } from 'i18next';
|
||||
import { useCallback, useMemo, useState } from 'react';
|
||||
import { useParams, useSearchParams } from 'umi';
|
||||
import { DataSourceInfo, DataSourceKey } from './contant';
|
||||
import { DataSourceKey, useDataSourceInfo } from './contant';
|
||||
import { IDataSorceInfo, IDataSource, IDataSourceBase } from './interface';
|
||||
|
||||
export const useListDataSource = () => {
|
||||
const { dataSourceInfo } = useDataSourceInfo();
|
||||
const { data: list, isFetching } = useQuery<IDataSource[]>({
|
||||
queryKey: ['data-source'],
|
||||
queryFn: async () => {
|
||||
@ -49,12 +50,12 @@ export const useListDataSource = () => {
|
||||
[];
|
||||
Object.keys(categorizedData).forEach((key: string) => {
|
||||
const k = key as DataSourceKey;
|
||||
if (DataSourceInfo[k]) {
|
||||
if (dataSourceInfo[k]) {
|
||||
sourceList.push({
|
||||
id: k,
|
||||
name: DataSourceInfo[k].name,
|
||||
description: DataSourceInfo[k].description,
|
||||
icon: DataSourceInfo[k].icon,
|
||||
name: dataSourceInfo[k].name,
|
||||
description: dataSourceInfo[k].description,
|
||||
icon: dataSourceInfo[k].icon,
|
||||
list: categorizedData[k] || [],
|
||||
});
|
||||
}
|
||||
|
||||
@ -10,21 +10,21 @@ import {
|
||||
} from '../components/user-setting-header';
|
||||
import AddDataSourceModal from './add-datasource-modal';
|
||||
import { AddedSourceCard } from './component/added-source-card';
|
||||
import { DataSourceInfo, DataSourceKey } from './contant';
|
||||
import { DataSourceKey, useDataSourceInfo } from './contant';
|
||||
import { useAddDataSource, useListDataSource } from './hooks';
|
||||
import { IDataSorceInfo } from './interface';
|
||||
|
||||
const dataSourceTemplates = Object.values(DataSourceKey).map((id) => {
|
||||
return {
|
||||
id,
|
||||
name: DataSourceInfo[id].name,
|
||||
description: DataSourceInfo[id].description,
|
||||
icon: DataSourceInfo[id].icon,
|
||||
};
|
||||
});
|
||||
|
||||
const DataSource = () => {
|
||||
const { t } = useTranslation();
|
||||
const { dataSourceInfo } = useDataSourceInfo();
|
||||
const dataSourceTemplates = Object.values(DataSourceKey).map((id) => {
|
||||
return {
|
||||
id,
|
||||
name: dataSourceInfo[id].name,
|
||||
description: dataSourceInfo[id].description,
|
||||
icon: dataSourceInfo[id].icon,
|
||||
};
|
||||
});
|
||||
|
||||
// useListTenantUser();
|
||||
const { categorizedList } = useListDataSource();
|
||||
|
||||
@ -43,3 +43,11 @@ export interface IDataSourceLog {
|
||||
tenant_id: string;
|
||||
timeout_secs: number;
|
||||
}
|
||||
|
||||
interface IDataSourceInfoItem {
|
||||
name: string;
|
||||
description: string;
|
||||
icon: JSX.Element;
|
||||
}
|
||||
|
||||
export type IDataSourceInfoMap = Record<DataSourceKey, IDataSourceInfoItem>;
|
||||
|
||||
@ -11,12 +11,13 @@ import {
|
||||
} from '@/hooks/use-user-setting-request';
|
||||
import { cn } from '@/lib/utils';
|
||||
import { Routes } from '@/routes';
|
||||
import { t } from 'i18next';
|
||||
import { TFunction } from 'i18next';
|
||||
import { Banknote, Box, Server, Unplug, User, Users } from 'lucide-react';
|
||||
import { useEffect } from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { useHandleMenuClick } from './hooks';
|
||||
|
||||
const menuItems = [
|
||||
const menuItems = (t: TFunction) => [
|
||||
{ icon: Server, label: t('setting.dataSources'), key: Routes.DataSource },
|
||||
{ icon: Box, label: t('setting.model'), key: Routes.Model },
|
||||
{ icon: Banknote, label: 'MCP', key: Routes.Mcp },
|
||||
@ -32,12 +33,12 @@ const menuItems = [
|
||||
// { icon: Cog, label: t('setting.system'), key: Routes.System },
|
||||
// { icon: Banknote, label: 'Plan', key: Routes.Plan },
|
||||
];
|
||||
|
||||
export function SideBar() {
|
||||
const pathName = useSecondPathName();
|
||||
const { data: userInfo } = useFetchUserInfo();
|
||||
const { handleMenuClick, active } = useHandleMenuClick();
|
||||
const { version, fetchSystemVersion } = useFetchSystemVersion();
|
||||
const { t } = useTranslation();
|
||||
useEffect(() => {
|
||||
if (location.host !== Domain) {
|
||||
fetchSystemVersion();
|
||||
@ -56,7 +57,7 @@ export function SideBar() {
|
||||
<p className="text-sm text-text-primary">{userInfo?.email}</p>
|
||||
</div>
|
||||
<div className="flex-1 overflow-auto">
|
||||
{menuItems.map((item, idx) => {
|
||||
{menuItems(t).map((item, idx) => {
|
||||
const hoverKey = pathName === item.key;
|
||||
return (
|
||||
<div key={idx}>
|
||||
|
||||
Reference in New Issue
Block a user