diff --git a/web/src/components/dynamic-form.tsx b/web/src/components/dynamic-form.tsx index 2926f32b6..b87ca6a7b 100644 --- a/web/src/components/dynamic-form.tsx +++ b/web/src/components/dynamic-form.tsx @@ -11,6 +11,7 @@ import { DefaultValues, FieldValues, SubmitHandler, + UseFormTrigger, useForm, useFormContext, } from 'react-hook-form'; @@ -99,8 +100,9 @@ interface DynamicFormProps { // Form ref interface export interface DynamicFormRef { submit: () => void; - getValues: () => any; + getValues: (name?: string) => any; reset: (values?: any) => void; + trigger: UseFormTrigger; 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); diff --git a/web/src/components/slider-input-form-field.tsx b/web/src/components/slider-input-form-field.tsx index 3bfbfea82..a15b358ce 100644 --- a/web/src/components/slider-input-form-field.tsx +++ b/web/src/components/slider-input-form-field.tsx @@ -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 ( + field.onChange(percentage ? value / 100 : value) + } + max={displayMax} + min={displayMin} + step={displayStep} > @@ -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, + ); + } + }} > diff --git a/web/src/components/ui/modal/modal.tsx b/web/src/components/ui/modal/modal.tsx index 13de06cf8..c856e1dd6 100644 --- a/web/src/components/ui/modal/modal.tsx +++ b/web/src/components/ui/modal/modal.tsx @@ -174,20 +174,23 @@ const Modal: ModalType = ({ onClick={() => maskClosable && onOpenChange?.(false)} > e.stopPropagation()} > {/* title */} - {(title || closable) && ( + {title && (
@@ -196,19 +199,19 @@ const Modal: ModalType = ({ {title} )} - {closable && ( - - - - )}
)} + {closable && ( + + + + )} {/* content */}
diff --git a/web/src/locales/en.ts b/web/src/locales/en.ts index a4f4fae5d..fa536ce1c 100644 --- a/web/src/locales/en.ts +++ b/web/src/locales/en.ts @@ -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', diff --git a/web/src/locales/zh.ts b/web/src/locales/zh.ts index 50b2faae3..85be01db7 100644 --- a/web/src/locales/zh.ts +++ b/web/src/locales/zh.ts @@ -101,6 +101,7 @@ export default { doc: '文档', searchKnowledgePlaceholder: '搜索', noMoreData: '没有更多数据了', + parserRequired: '分块方法必填', }, knowledgeDetails: { localUpload: '本地上传', diff --git a/web/src/pages/dataset/dataset-overview/overview-table.tsx b/web/src/pages/dataset/dataset-overview/overview-table.tsx index a0aa79702..a09f56c9a 100644 --- a/web/src/pages/dataset/dataset-overview/overview-table.tsx +++ b/web/src/pages/dataset/dataset-overview/overview-table.tsx @@ -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[] = [ @@ -117,8 +119,8 @@ export const getFileLogsTableColumns = ( ) : (
{ - DataSourceInfo[ - row.original.source_from as keyof typeof DataSourceInfo + dataSourceInfo[ + row.original.source_from as keyof typeof dataSourceInfo ].icon }
@@ -368,7 +370,7 @@ const FileLogsTable: FC = ({ setLogInfo(logDetail); setIsModalVisible(true); }; - + const { dataSourceInfo } = useDataSourceInfo(); const columns = useMemo(() => { return active === LogTabs.FILE_LOGS ? getFileLogsTableColumns( @@ -376,6 +378,7 @@ const FileLogsTable: FC = ({ showLog, kowledgeId || '', navigateToDataflowResult, + dataSourceInfo, ) : getDatasetLogsTableColumns(t, showLog); }, [active, t]); diff --git a/web/src/pages/dataset/dataset-setting/components/link-data-source.tsx b/web/src/pages/dataset/dataset-setting/components/link-data-source.tsx index c3d89a860..f101f14da 100644 --- a/web/src/pages/dataset/dataset-setting/components/link-data-source.tsx +++ b/web/src/pages/dataset/dataset-setting/components/link-data-source.tsx @@ -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) => {
{icon}
- {DataSourceInfo[source].name} + {dataSourceInfo[source].name}
{name}
@@ -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; }); diff --git a/web/src/pages/dataset/dataset-setting/configuration/common-item.tsx b/web/src/pages/dataset/dataset-setting/configuration/common-item.tsx index 2e6b7400a..a8c67269d 100644 --- a/web/src/pages/dataset/dataset-setting/configuration/common-item.tsx +++ b/web/src/pages/dataset/dataset-setting/configuration/common-item.tsx @@ -291,9 +291,10 @@ export function EnableTocToggle() { export function OverlappedPercent() { return ( ); diff --git a/web/src/pages/dataset/dataset-setting/index.tsx b/web/src/pages/dataset/dataset-setting/index.tsx index accbedda4..799cc569b 100644 --- a/web/src/pages/dataset/dataset-setting/index.tsx +++ b/web/src/pages/dataset/dataset-setting/index.tsx @@ -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(); const [sourceData, setSourceData] = useState(); @@ -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 || '', }; }); diff --git a/web/src/pages/dataset/dataset/use-dataset-table-columns.tsx b/web/src/pages/dataset/dataset/use-dataset-table-columns.tsx index 845c9e76a..83fd3d7d6 100644 --- a/web/src/pages/dataset/dataset/use-dataset-table-columns.tsx +++ b/web/src/pages/dataset/dataset/use-dataset-table-columns.tsx @@ -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({ ) : (
{ - DataSourceInfo[ - row.original.source_type as keyof typeof DataSourceInfo + dataSourceInfo[ + row.original.source_type as keyof typeof dataSourceInfo ]?.icon }
diff --git a/web/src/pages/next-searches/index.tsx b/web/src/pages/next-searches/index.tsx index 89a44a9cc..96ada4706 100644 --- a/web/src/pages/next-searches/index.tsx +++ b/web/src/pages/next-searches/index.tsx @@ -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={} + title={initialSearchName || t('createSearch')} > )} diff --git a/web/src/pages/user-setting/data-source/component/added-source-card.tsx b/web/src/pages/user-setting/data-source/component/added-source-card.tsx index 424d53fa6..aeffe80ba 100644 --- a/web/src/pages/user-setting/data-source/component/added-source-card.tsx +++ b/web/src/pages/user-setting/data-source/component/added-source-card.tsx @@ -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); }, diff --git a/web/src/pages/user-setting/data-source/component/delete-source-modal.tsx b/web/src/pages/user-setting/data-source/component/delete-source-modal.tsx index a9f0f9a22..8f8b5ed02 100644 --- a/web/src/pages/user-setting/data-source/component/delete-source-modal.tsx +++ b/web/src/pages/user-setting/data-source/component/delete-source-modal.tsx @@ -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 = Partial & { data?: T; type?: 'delete' | 'unlink'; onOk?: (data?: T) => void; + dataSourceInfo: IDataSourceInfoMap; }; export const delSourceModal = ( props: IDelSourceModalProps, ) => { - 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 = ( )}
- {data?.source ? DataSourceInfo[data?.source].icon : ''} + {data?.source ? dataSourceInfo[data?.source].icon : ''}
{/*
diff --git a/web/src/pages/user-setting/data-source/contant.tsx b/web/src/pages/user-setting/data-source/contant.tsx index ba80c2a55..483afc432 100644 --- a/web/src/pages/user-setting/data-source/contant.tsx +++ b/web/src/pages/user-setting/data-source/contant.tsx @@ -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,62 +25,75 @@ export enum DataSourceKey { // TEAMS = 'teams', } -export const DataSourceInfo = { - [DataSourceKey.S3]: { - name: 'S3', - description: t(`setting.${DataSourceKey.S3}Description`), - icon: , - }, - [DataSourceKey.NOTION]: { - name: 'Notion', - description: t(`setting.${DataSourceKey.NOTION}Description`), - icon: , - }, - [DataSourceKey.DISCORD]: { - name: 'Discord', - description: t(`setting.${DataSourceKey.DISCORD}Description`), - icon: , - }, - [DataSourceKey.CONFLUENCE]: { - name: 'Confluence', - description: t(`setting.${DataSourceKey.CONFLUENCE}Description`), - icon: , - }, - [DataSourceKey.GOOGLE_DRIVE]: { - name: 'Google Drive', - description: t(`setting.${DataSourceKey.GOOGLE_DRIVE}Description`), - icon: , - }, - [DataSourceKey.GMAIL]: { - name: 'Gmail', - description: t(`setting.${DataSourceKey.GMAIL}Description`), - icon: , - }, - [DataSourceKey.MOODLE]: { - name: 'Moodle', - description: t(`setting.${DataSourceKey.MOODLE}Description`), - icon: , - }, - [DataSourceKey.JIRA]: { - name: 'Jira', - description: t(`setting.${DataSourceKey.JIRA}Description`), - icon: , - }, - [DataSourceKey.WEBDAV]: { - name: 'WebDAV', - description: t(`setting.${DataSourceKey.WEBDAV}Description`), - icon: , - }, - [DataSourceKey.DROPBOX]: { - name: 'Dropbox', - description: t(`setting.${DataSourceKey.DROPBOX}Description`), - icon: , - }, - [DataSourceKey.BOX]: { - name: 'Box', - description: t(`setting.${DataSourceKey.BOX}Description`), - icon: , - }, +export const generateDataSourceInfo = (t: TFunction) => { + return { + [DataSourceKey.S3]: { + name: 'S3', + description: t(`setting.${DataSourceKey.S3}Description`), + icon: , + }, + [DataSourceKey.NOTION]: { + name: 'Notion', + description: t(`setting.${DataSourceKey.NOTION}Description`), + icon: , + }, + [DataSourceKey.DISCORD]: { + name: 'Discord', + description: t(`setting.${DataSourceKey.DISCORD}Description`), + icon: , + }, + [DataSourceKey.CONFLUENCE]: { + name: 'Confluence', + description: t(`setting.${DataSourceKey.CONFLUENCE}Description`), + icon: , + }, + [DataSourceKey.GOOGLE_DRIVE]: { + name: 'Google Drive', + description: t(`setting.${DataSourceKey.GOOGLE_DRIVE}Description`), + icon: , + }, + [DataSourceKey.GMAIL]: { + name: 'Gmail', + description: t(`setting.${DataSourceKey.GMAIL}Description`), + icon: , + }, + [DataSourceKey.MOODLE]: { + name: 'Moodle', + description: t(`setting.${DataSourceKey.MOODLE}Description`), + icon: , + }, + [DataSourceKey.JIRA]: { + name: 'Jira', + description: t(`setting.${DataSourceKey.JIRA}Description`), + icon: , + }, + [DataSourceKey.WEBDAV]: { + name: 'WebDAV', + description: t(`setting.${DataSourceKey.WEBDAV}Description`), + icon: , + }, + [DataSourceKey.DROPBOX]: { + name: 'Dropbox', + description: t(`setting.${DataSourceKey.DROPBOX}Description`), + icon: , + }, + [DataSourceKey.BOX]: { + name: 'Box', + description: t(`setting.${DataSourceKey.BOX}Description`), + icon: , + }, + }; +}; + +export const useDataSourceInfo = () => { + const { t } = useTranslation(); + const [dataSourceInfo, setDataSourceInfo] = useState( + generateDataSourceInfo(t) as IDataSourceInfoMap, + ); + useEffect(() => { + setDataSourceInfo(generateDataSourceInfo(t)); + }, [t]); + return { dataSourceInfo }; }; export const DataSourceFormBaseFields = [ diff --git a/web/src/pages/user-setting/data-source/data-source-detail-page/index.tsx b/web/src/pages/user-setting/data-source/data-source-detail-page/index.tsx index f399fd21d..5f24f8e24 100644 --- a/web/src/pages/user-setting/data-source/data-source-detail-page/index.tsx +++ b/web/src/pages/user-setting/data-source/data-source-detail-page/index.tsx @@ -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]); diff --git a/web/src/pages/user-setting/data-source/hooks.ts b/web/src/pages/user-setting/data-source/hooks.ts index 63b2f1a80..a07e3c72d 100644 --- a/web/src/pages/user-setting/data-source/hooks.ts +++ b/web/src/pages/user-setting/data-source/hooks.ts @@ -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({ 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] || [], }); } diff --git a/web/src/pages/user-setting/data-source/index.tsx b/web/src/pages/user-setting/data-source/index.tsx index af7d6c650..9830f4549 100644 --- a/web/src/pages/user-setting/data-source/index.tsx +++ b/web/src/pages/user-setting/data-source/index.tsx @@ -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(); diff --git a/web/src/pages/user-setting/data-source/interface.ts b/web/src/pages/user-setting/data-source/interface.ts index 5e237857e..5cca99748 100644 --- a/web/src/pages/user-setting/data-source/interface.ts +++ b/web/src/pages/user-setting/data-source/interface.ts @@ -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; diff --git a/web/src/pages/user-setting/sidebar/index.tsx b/web/src/pages/user-setting/sidebar/index.tsx index 476bf9ce6..b0982e3ca 100644 --- a/web/src/pages/user-setting/sidebar/index.tsx +++ b/web/src/pages/user-setting/sidebar/index.tsx @@ -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() {

{userInfo?.email}

- {menuItems.map((item, idx) => { + {menuItems(t).map((item, idx) => { const hoverKey = pathName === item.key; return (