From 39351970d058b2a71c957726a53a89d8e318ceaf Mon Sep 17 00:00:00 2001 From: CorrectRoadH Date: Fri, 14 Jul 2023 13:09:21 +0800 Subject: [PATCH] feat: implement memo chat frontend (#1938) * feat: implment backend function * feat: implment frontend component * stash * eslint * eslint * eslint * delete node * stash * refactor the style * eslint * eslint * eslint * fix build error * add dep * Update web/src/components/MemosChat/ConversationTab.tsx Co-authored-by: boojack * Update web/src/components/MemosChat/ConversationTab.tsx Co-authored-by: boojack * feat: change the name * disable for vistor --------- Co-authored-by: boojack --- server/server.go | 2 +- web/package.json | 3 + web/pnpm-lock.yaml | 24 ++- web/src/components/Header.tsx | 14 ++ .../components/MemosChat/ConversationTab.tsx | 33 +++ .../components/MemosChat/MemosChatInput.tsx | 42 ++++ .../components/MemosChat/MemosChatMessage.tsx | 31 +++ web/src/helpers/api.ts | 27 +++ web/src/locales/en.json | 5 +- web/src/locales/ja.json | 3 +- web/src/locales/zh-Hans.json | 2 +- web/src/locales/zh-Hant.json | 3 +- web/src/pages/MemosChat.tsx | 201 ++++++++++++++++++ web/src/router/index.tsx | 21 ++ web/src/store/zustand/conversation.ts | 43 ++++ web/src/store/zustand/message.ts | 37 ++++ web/src/utils/uuid.ts | 5 + 17 files changed, 489 insertions(+), 7 deletions(-) create mode 100644 web/src/components/MemosChat/ConversationTab.tsx create mode 100644 web/src/components/MemosChat/MemosChatInput.tsx create mode 100644 web/src/components/MemosChat/MemosChatMessage.tsx create mode 100644 web/src/pages/MemosChat.tsx create mode 100644 web/src/store/zustand/conversation.ts create mode 100644 web/src/store/zustand/message.ts create mode 100644 web/src/utils/uuid.ts diff --git a/server/server.go b/server/server.go index 81fc1cd7..78e82f14 100644 --- a/server/server.go +++ b/server/server.go @@ -67,7 +67,7 @@ func NewServer(ctx context.Context, profile *profile.Profile, store *store.Store Skipper: func(c echo.Context) bool { // this is a hack to skip timeout for openai chat streaming // because streaming require to flush response. But the timeout middleware will break it. - return c.Request().URL.Path == "/api/openai/chat-streaming" + return c.Request().URL.Path == "/api/v1/openai/chat-streaming" }, ErrorMessage: "Request timeout", Timeout: 30 * time.Second, diff --git a/web/package.json b/web/package.json index 2f2898e4..305da2ba 100644 --- a/web/package.json +++ b/web/package.json @@ -10,6 +10,7 @@ "dependencies": { "@emotion/react": "^11.10.5", "@emotion/styled": "^11.10.5", + "@microsoft/fetch-event-source": "^2.0.1", "@mui/joy": "^5.0.0-alpha.75", "@reduxjs/toolkit": "^1.8.1", "axios": "^0.27.2", @@ -29,6 +30,7 @@ "react-use": "^17.4.0", "semver": "^7.3.8", "tailwindcss": "^3.2.4", + "uuid": "^9.0.0", "zustand": "^4.3.6" }, "devDependencies": { @@ -38,6 +40,7 @@ "@types/react": "^18.0.26", "@types/react-dom": "^18.0.10", "@types/semver": "^7.3.13", + "@types/uuid": "^9.0.2", "@typescript-eslint/eslint-plugin": "^5.6.0", "@typescript-eslint/parser": "^5.6.0", "@vitejs/plugin-react-swc": "^3.3.0", diff --git a/web/pnpm-lock.yaml b/web/pnpm-lock.yaml index 0bd016c1..569c2d5c 100644 --- a/web/pnpm-lock.yaml +++ b/web/pnpm-lock.yaml @@ -1,4 +1,4 @@ -lockfileVersion: '6.1' +lockfileVersion: '6.0' settings: autoInstallPeers: true @@ -11,6 +11,9 @@ dependencies: '@emotion/styled': specifier: ^11.10.5 version: 11.10.5(@emotion/react@11.10.5)(@types/react@18.0.26)(react@18.2.0) + '@microsoft/fetch-event-source': + specifier: ^2.0.1 + version: 2.0.1 '@mui/joy': specifier: ^5.0.0-alpha.75 version: 5.0.0-alpha.75(@emotion/react@11.10.5)(@emotion/styled@11.10.5)(@types/react@18.0.26)(react-dom@18.2.0)(react@18.2.0) @@ -68,6 +71,9 @@ dependencies: tailwindcss: specifier: ^3.2.4 version: 3.2.4(postcss@8.4.21) + uuid: + specifier: ^9.0.0 + version: 9.0.0 zustand: specifier: ^4.3.6 version: 4.3.6(react@18.2.0) @@ -91,6 +97,9 @@ devDependencies: '@types/semver': specifier: ^7.3.13 version: 7.3.13 + '@types/uuid': + specifier: ^9.0.2 + version: 9.0.2 '@typescript-eslint/eslint-plugin': specifier: ^5.6.0 version: 5.6.0(@typescript-eslint/parser@5.6.0)(eslint@8.4.1)(typescript@5.0.4) @@ -578,6 +587,10 @@ packages: '@jridgewell/sourcemap-codec': 1.4.14 dev: true + /@microsoft/fetch-event-source@2.0.1: + resolution: {integrity: sha512-W6CLUJ2eBMw3Rec70qrsEW0jOm/3twwJv21mrmj2yORiaVmVYGS4sSS5yUwvQc1ZlDLYGPnClVWmUUMagKNsfA==} + dev: false + /@mui/base@5.0.0-alpha.125(@types/react@18.0.26)(react-dom@18.2.0)(react@18.2.0): resolution: {integrity: sha512-hAHJJ97SATu6SrkLH/HsAayK1zMZt89lrWyKuAInBKVyn363H78d1MnwyZwre9vDK5MrPoDL/NnZxtAXhwTnBA==} engines: {node: '>=12.0.0'} @@ -961,6 +974,10 @@ packages: resolution: {integrity: sha512-EwmlvuaxPNej9+T4v5AuBPJa2x2UOJVdjCtDHgcDqitUeOtjnJKJ+apYjVcAoBEMjKW1VVFGZLUb5+qqa09XFA==} dev: false + /@types/uuid@9.0.2: + resolution: {integrity: sha512-kNnC1GFBLuhImSnV7w4njQkUiJi0ZXUycu1rUaouPqiKlXkh77JKgdRnTAp1x5eBwcIwbtI+3otwzuIDEuDoxQ==} + dev: true + /@typescript-eslint/eslint-plugin@5.6.0(@typescript-eslint/parser@5.6.0)(eslint@8.4.1)(typescript@5.0.4): resolution: {integrity: sha512-MIbeMy5qfLqtgs1hWd088k1hOuRsN9JrHUPwVVKCD99EOUqScd7SrwoZl4Gso05EAP9w1kvLWUVGJOVpRPkDPA==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} @@ -3403,6 +3420,11 @@ packages: resolution: {integrity: sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==} dev: false + /uuid@9.0.0: + resolution: {integrity: sha512-MXcSTerfPa4uqyzStbRoTgt5XIe3x5+42+q1sDuy3R5MDk66URdLMOZe5aPX/SQd+kuYAh0FdP/pO28IkQyTeg==} + hasBin: true + dev: false + /v8-compile-cache@2.3.0: resolution: {integrity: sha512-l8lCEmLcLYZh4nbunNZvQCJc5pv7+RCwa8q/LdUx8u7lsWvPDKmpodJAJNwkAhJC//dFY48KuIEmjtd4RViDrA==} dev: true diff --git a/web/src/components/Header.tsx b/web/src/components/Header.tsx index 19f033a9..9608db5c 100644 --- a/web/src/components/Header.tsx +++ b/web/src/components/Header.tsx @@ -103,8 +103,22 @@ const Header = () => { {t("common.explore")} + {!isVisitorMode && ( <> + + `${ + isActive && "bg-white dark:bg-zinc-700 shadow" + } px-4 pr-5 py-2 rounded-full flex flex-row items-center text-lg text-gray-800 dark:text-gray-300 hover:bg-white hover:shadow dark:hover:bg-zinc-700` + } + > + <> + {t("memo-chat.title")} + + void; + closeConversation: (e: any) => void; +} + +const ConversationTab = ({ item, selectedConversationId, setSelectedConversationId, closeConversation }: ConversationTabProps) => { + return ( +
{ + setSelectedConversationId(item.messageStorageId); + }} + > +
{item.name}
+ { + closeConversation(e); + }} + /> +
+ ); +}; + +export default ConversationTab; diff --git a/web/src/components/MemosChat/MemosChatInput.tsx b/web/src/components/MemosChat/MemosChatInput.tsx new file mode 100644 index 00000000..4c56f0c8 --- /dev/null +++ b/web/src/components/MemosChat/MemosChatInput.tsx @@ -0,0 +1,42 @@ +import Icon from "@/components/Icon"; +import Textarea from "@mui/joy/Textarea/Textarea"; +import { useTranslation } from "react-i18next"; + +interface MemosChatInputProps { + question: string; + handleQuestionTextareaChange: any; + setIsInIME: any; + handleKeyDown: any; + handleSendQuestionButtonClick: any; +} +const MemosChatInput = ({ + question, + handleQuestionTextareaChange, + setIsInIME, + handleKeyDown, + handleSendQuestionButtonClick, +}: MemosChatInputProps) => { + const { t } = useTranslation(); + + return ( +
+