diff --git a/web/src/app.tsx b/web/src/app.tsx index 51ce7564d..746b64995 100644 --- a/web/src/app.tsx +++ b/web/src/app.tsx @@ -1,16 +1,16 @@ -import { ConfigProvider } from 'antd'; -import React, { ReactNode } from 'react'; +import { App, ConfigProvider } from 'antd'; +import { ReactNode } from 'react'; export function rootContainer(container: ReactNode) { - return React.createElement( - ConfigProvider, - { - theme: { + return ( + + {container} + ); } diff --git a/web/src/components/deleting-confirm/index.less b/web/src/components/deleting-confirm/index.less deleted file mode 100644 index e69de29bb..000000000 diff --git a/web/src/components/deleting-confirm/index.tsx b/web/src/components/deleting-confirm/index.tsx deleted file mode 100644 index bd6377ad6..000000000 --- a/web/src/components/deleting-confirm/index.tsx +++ /dev/null @@ -1,39 +0,0 @@ -import { ExclamationCircleFilled } from '@ant-design/icons'; -import { Modal } from 'antd'; - -const { confirm } = Modal; - -interface IProps { - onOk?: (...args: any[]) => any; - onCancel?: (...args: any[]) => any; -} - -export const showDeleteConfirm = ({ - onOk, - onCancel, -}: IProps): Promise => { - return new Promise((resolve, reject) => { - confirm({ - title: 'Are you sure delete this item?', - icon: , - content: 'Some descriptions', - okText: 'Yes', - okType: 'danger', - cancelText: 'No', - async onOk() { - try { - const ret = await onOk?.(); - resolve(ret); - console.info(ret); - } catch (error) { - reject(error); - } - }, - onCancel() { - onCancel?.(); - }, - }); - }); -}; - -export default showDeleteConfirm; diff --git a/web/src/components/svg-icon.tsx b/web/src/components/svg-icon.tsx index c0a625c30..f740f2c9c 100644 --- a/web/src/components/svg-icon.tsx +++ b/web/src/components/svg-icon.tsx @@ -4,7 +4,6 @@ import { IconComponentProps } from '@ant-design/icons/lib/components/Icon'; const importAll = (requireContext: __WebpackModuleApi.RequireContext) => { const list = requireContext.keys().map((key) => { const name = key.replace(/\.\/(.*)\.\w+$/, '$1'); - console.log(name, requireContext(key)); return { name, value: requireContext(key) }; }); return list; diff --git a/web/src/hooks/commonHooks.ts b/web/src/hooks/commonHooks.tsx similarity index 60% rename from web/src/hooks/commonHooks.ts rename to web/src/hooks/commonHooks.tsx index 21e6641e1..b087fb95b 100644 --- a/web/src/hooks/commonHooks.ts +++ b/web/src/hooks/commonHooks.tsx @@ -1,5 +1,8 @@ +import { ExclamationCircleFilled } from '@ant-design/icons'; +import { App } from 'antd'; import isEqual from 'lodash/isEqual'; -import { useEffect, useRef, useState } from 'react'; +import { useCallback, useEffect, useRef, useState } from 'react'; +import { useTranslation } from 'react-i18next'; export const useSetModalState = () => { const [visible, setVisible] = useState(false); @@ -72,3 +75,43 @@ export function useDynamicSVGImport( return { error, loading, SvgIcon: ImportedIconRef.current }; } + +interface IProps { + onOk?: (...args: any[]) => any; + onCancel?: (...args: any[]) => any; +} + +export const useShowDeleteConfirm = () => { + const { modal } = App.useApp(); + const { t } = useTranslation(); + + const showDeleteConfirm = useCallback( + ({ onOk, onCancel }: IProps): Promise => { + return new Promise((resolve, reject) => { + modal.confirm({ + title: t('common.deleteModalTitle'), + icon: , + // content: 'Some descriptions', + okText: 'Yes', + okType: 'danger', + cancelText: 'No', + async onOk() { + try { + const ret = await onOk?.(); + resolve(ret); + console.info(ret); + } catch (error) { + reject(error); + } + }, + onCancel() { + onCancel?.(); + }, + }); + }); + }, + [t, modal], + ); + + return showDeleteConfirm; +}; diff --git a/web/src/hooks/knowledgeHook.ts b/web/src/hooks/knowledgeHook.ts index 8a0f7a32c..e34917bef 100644 --- a/web/src/hooks/knowledgeHook.ts +++ b/web/src/hooks/knowledgeHook.ts @@ -1,4 +1,4 @@ -import showDeleteConfirm from '@/components/deleting-confirm'; +import { useShowDeleteConfirm } from '@/hooks/commonHooks'; import { IKnowledge } from '@/interfaces/database/knowledge'; import { useCallback, useEffect, useMemo } from 'react'; import { useDispatch, useSearchParams, useSelector } from 'umi'; @@ -17,6 +17,7 @@ export const useDeleteDocumentById = (): { } => { const dispatch = useDispatch(); const knowledgeBaseId = useKnowledgeBaseId(); + const showDeleteConfirm = useShowDeleteConfirm(); const removeDocument = (documentId: string) => () => { return dispatch({ @@ -79,6 +80,7 @@ export const useDeleteChunkByIds = (): { removeChunk: (chunkIds: string[], documentId: string) => Promise; } => { const dispatch = useDispatch(); + const showDeleteConfirm = useShowDeleteConfirm(); const removeChunk = useCallback( (chunkIds: string[], documentId: string) => () => { @@ -97,7 +99,7 @@ export const useDeleteChunkByIds = (): { (chunkIds: string[], documentId: string): Promise => { return showDeleteConfirm({ onOk: removeChunk(chunkIds, documentId) }); }, - [removeChunk], + [removeChunk, showDeleteConfirm], ); return { diff --git a/web/src/layouts/components/header/index.tsx b/web/src/layouts/components/header/index.tsx index 4dc01915f..d0d2827ae 100644 --- a/web/src/layouts/components/header/index.tsx +++ b/web/src/layouts/components/header/index.tsx @@ -8,6 +8,7 @@ import styles from './index.less'; import { useNavigateWithFromState } from '@/hooks/routeHook'; import { useCallback, useMemo } from 'react'; +import { useTranslation } from 'react-i18next'; import { useLocation } from 'umi'; const { Header } = Layout; @@ -18,14 +19,15 @@ const RagHeader = () => { } = theme.useToken(); const navigate = useNavigateWithFromState(); const { pathname } = useLocation(); + const { t } = useTranslation('translation', { keyPrefix: 'header' }); const tagsData = useMemo( () => [ - { path: '/knowledge', name: 'Knowledge Base', icon: KnowledgeBaseIcon }, - { path: '/chat', name: 'Chat', icon: StarIon }, + { path: '/knowledge', name: t('knowledgeBase'), icon: KnowledgeBaseIcon }, + { path: '/chat', name: t('chat'), icon: StarIon }, // { path: '/file', name: 'File Management', icon: FileIcon }, ], - [], + [t], ); const currentPath = useMemo(() => { diff --git a/web/src/locales/en.json b/web/src/locales/en.json index 9f0778ec1..705e7fb8e 100644 --- a/web/src/locales/en.json +++ b/web/src/locales/en.json @@ -1,12 +1,41 @@ { - "login": { "login": "Sign in" }, + "common": { + "delete": "Delete", + "deleteModalTitle": "Are you sure delete this item?" + }, + "login": { + "login": "Sign in", + "signUp": "Sign up", + "loginDescription": "We’re so excited to see you again!", + "registerDescription": "Glad to have you on board!", + "emailLabel": "Email", + "emailPlaceholder": "Please input email", + "passwordLabel": "Password", + "passwordPlaceholder": "Please input password", + "rememberMe": "Remember me", + "signInTip": "Don’t have an account?", + "signUpTip": "Already have an account?", + "nicknameLabel": "Nickname", + "nicknamePlaceholder": "Please input nickname", + "register": "Create an account", + "continue": "Continue" + }, "header": { + "knowledgeBase": "Knowledge Base", + "chat": "Chat", "register": "Register", "signin": "Sign in", "home": "Home", "setting": "用户设置", "logout": "登出" }, + "knowledgeList": { + "welcome": "Welcome back", + "description": "Which database are we going to use today?", + "createKnowledgeBase": "Create knowledge base", + "name": "Name", + "namePlaceholder": "Please input name!" + }, "footer": { "detail": "All rights reserved @ React" }, diff --git a/web/src/pages/add-knowledge/components/knowledge-file/model.ts b/web/src/pages/add-knowledge/components/knowledge-file/model.ts index 97a75a514..f946c9d78 100644 --- a/web/src/pages/add-knowledge/components/knowledge-file/model.ts +++ b/web/src/pages/add-knowledge/components/knowledge-file/model.ts @@ -203,7 +203,6 @@ const model: DvaModel = { const documentId = payload; try { const ret = yield call(getDocumentFile, documentId); - console.info('fetch_document_file:', ret); return ret; } catch (error) { console.warn(error); @@ -238,7 +237,6 @@ const model: DvaModel = { payload: { current: 1, pageSize: 10 }, }); } - console.info(location); }); }, }, diff --git a/web/src/pages/add-knowledge/components/knowledge-file/parsing-action-cell/index.tsx b/web/src/pages/add-knowledge/components/knowledge-file/parsing-action-cell/index.tsx index 55fd93d3f..480fa1537 100644 --- a/web/src/pages/add-knowledge/components/knowledge-file/parsing-action-cell/index.tsx +++ b/web/src/pages/add-knowledge/components/knowledge-file/parsing-action-cell/index.tsx @@ -1,4 +1,4 @@ -import showDeleteConfirm from '@/components/deleting-confirm'; +import { useShowDeleteConfirm } from '@/hooks/commonHooks'; import { useRemoveDocument } from '@/hooks/documentHooks'; import { IKnowledgeFile } from '@/interfaces/database/knowledge'; import { api_host } from '@/utils/api'; @@ -31,6 +31,7 @@ const ParsingActionCell = ({ const isRunning = isParserRunning(record.run); const removeDocument = useRemoveDocument(documentId); + const showDeleteConfirm = useShowDeleteConfirm(); const onRmDocument = () => { if (!isRunning) { diff --git a/web/src/pages/chat/hooks.ts b/web/src/pages/chat/hooks.ts index 725d8aa30..c81006e1d 100644 --- a/web/src/pages/chat/hooks.ts +++ b/web/src/pages/chat/hooks.ts @@ -1,7 +1,6 @@ -import showDeleteConfirm from '@/components/deleting-confirm'; import { MessageType } from '@/constants/chat'; import { fileIconMap } from '@/constants/common'; -import { useSetModalState } from '@/hooks/commonHooks'; +import { useSetModalState, useShowDeleteConfirm } from '@/hooks/commonHooks'; import { useOneNamespaceEffectsLoading } from '@/hooks/storeHooks'; import { IConversation, IDialog } from '@/interfaces/database/chat'; import { IChunk } from '@/interfaces/database/knowledge'; @@ -150,6 +149,7 @@ export const useSelectPromptConfigParameters = (): VariableTableDataType[] => { export const useRemoveDialog = () => { const dispatch = useDispatch(); + const showDeleteConfirm = useShowDeleteConfirm(); const removeDocument = (dialogIds: Array) => () => { return dispatch({ @@ -668,6 +668,7 @@ export const useRemoveConversation = () => { const dispatch = useDispatch(); const { dialogId } = useGetChatSearchParams(); const { handleClickConversation } = useClickConversationCard(); + const showDeleteConfirm = useShowDeleteConfirm(); const removeConversation = (conversationIds: Array) => async () => { const ret = await dispatch({ diff --git a/web/src/pages/knowledge/index.less b/web/src/pages/knowledge/index.less index ba92f652b..a13208101 100644 --- a/web/src/pages/knowledge/index.less +++ b/web/src/pages/knowledge/index.less @@ -44,4 +44,7 @@ .knowledgeCardContainer { padding: 0 60px; overflow: auto; + .knowledgeEmpty { + width: 100%; + } } diff --git a/web/src/pages/knowledge/index.tsx b/web/src/pages/knowledge/index.tsx index b8a3659a8..9206c2202 100644 --- a/web/src/pages/knowledge/index.tsx +++ b/web/src/pages/knowledge/index.tsx @@ -6,22 +6,22 @@ import { Button, Empty, Flex, Space, Spin } from 'antd'; import KnowledgeCard from './knowledge-card'; import KnowledgeCreatingModal from './knowledge-creating-modal'; +import { useTranslation } from 'react-i18next'; import styles from './index.less'; const Knowledge = () => { const { list, loading } = useFetchKnowledgeList(); const userInfo = useSelectUserInfo(); + const { t } = useTranslation('translation', { keyPrefix: 'knowledgeList' }); return (
- Welcome back, {userInfo.nickname} + {t('welcome')}, {userInfo.nickname} -

- Which database are we going to use today? -

+

{t('description')}

{/* { ); }) ) : ( - + )} diff --git a/web/src/pages/knowledge/knowledge-card/index.tsx b/web/src/pages/knowledge/knowledge-card/index.tsx index 4a6a2f610..bc7e337bb 100644 --- a/web/src/pages/knowledge/knowledge-card/index.tsx +++ b/web/src/pages/knowledge/knowledge-card/index.tsx @@ -1,5 +1,6 @@ import { ReactComponent as MoreIcon } from '@/assets/svg/more.svg'; import { KnowledgeRouteKey } from '@/constants/knowledge'; +import { useShowDeleteConfirm } from '@/hooks/commonHooks'; import { IKnowledge } from '@/interfaces/database/knowledge'; import { formatDate } from '@/utils/date'; import { @@ -11,7 +12,6 @@ import { import { Avatar, Card, Dropdown, MenuProps, Space } from 'antd'; import { useDispatch, useNavigate } from 'umi'; -import showDeleteConfirm from '@/components/deleting-confirm'; import styles from './index.less'; interface IProps { @@ -21,6 +21,7 @@ interface IProps { const KnowledgeCard = ({ item }: IProps) => { const navigate = useNavigate(); const dispatch = useDispatch(); + const showDeleteConfirm = useShowDeleteConfirm(); const removeKnowledge = () => { return dispatch({ diff --git a/web/src/pages/knowledge/knowledge-creating-modal/index.tsx b/web/src/pages/knowledge/knowledge-creating-modal/index.tsx index abb9c25f7..20eaa0668 100644 --- a/web/src/pages/knowledge/knowledge-creating-modal/index.tsx +++ b/web/src/pages/knowledge/knowledge-creating-modal/index.tsx @@ -1,6 +1,7 @@ import { IModalManagerChildrenProps } from '@/components/modal-manager'; import { KnowledgeRouteKey } from '@/constants/knowledge'; import { Form, Input, Modal } from 'antd'; +import { useTranslation } from 'react-i18next'; import { useDispatch, useNavigate, useSelector } from 'umi'; type FieldType = { @@ -17,6 +18,7 @@ const KnowledgeCreatingModal = ({ (state: any) => state.loading.effects['kSModel/createKb'], ); const navigate = useNavigate(); + const { t } = useTranslation('translation', { keyPrefix: 'knowledgeList' }); const handleOk = async () => { const ret = await form.validateFields(); @@ -50,7 +52,7 @@ const KnowledgeCreatingModal = ({ return ( - label="Name" + label={t('name')} name="name" - rules={[{ required: true, message: 'Please input name!' }]} + rules={[{ required: true, message: t('namePlaceholder') }]} > - + diff --git a/web/src/pages/login/index.tsx b/web/src/pages/login/index.tsx index d494c295e..1de7e933b 100644 --- a/web/src/pages/login/index.tsx +++ b/web/src/pages/login/index.tsx @@ -1,3 +1,4 @@ +import { useLogin, useRegister } from '@/hooks/loginHooks'; import { useOneNamespaceEffectsLoading } from '@/hooks/storeHooks'; import { rsaPsw } from '@/utils'; import { Button, Checkbox, Form, Input } from 'antd'; @@ -6,7 +7,6 @@ import { useTranslation } from 'react-i18next'; import { Icon, useNavigate } from 'umi'; import RightPanel from './right-panel'; -import { useLogin, useRegister } from '@/hooks/loginHooks'; import styles from './index.less'; const Login = () => { @@ -14,7 +14,7 @@ const Login = () => { const navigate = useNavigate(); const login = useLogin(); const register = useRegister(); - const { t } = useTranslation(); + const { t } = useTranslation('translation', { keyPrefix: 'login' }); // TODO: When the server address request is not accessible, the value of dva-loading always remains true. @@ -75,13 +75,11 @@ const Login = () => {
-
- {title === 'login' ? t('login.login') : 'Create an account'} -
+
{title === 'login' ? t('login') : 'Create an account'}
{title === 'login' - ? 'We’re so excited to see you again!' - : 'Glad to have you on board!'} + ? t('loginDescription') + : t('registerDescription')}
@@ -94,55 +92,52 @@ const Login = () => { - + {title === 'register' && ( - + )} {title === 'login' && ( - Remember me + {t('rememberMe')} )}
- {' '} {title === 'login' && (
- Don’t have an account? + {t('signInTip')}
)} {title === 'register' && (
- Already have an account? + {t('signUpTip')}
)} @@ -154,7 +149,7 @@ const Login = () => { onClick={onCheck} loading={signLoading} > - {title === 'login' ? 'Sign in' : 'Continue'} + {title === 'login' ? t('login') : t('continue')} {title === 'login' && ( <>