From 5cbf4cf352048761527c717caf9addc946bb4e2a Mon Sep 17 00:00:00 2001 From: utin-francis-peter Date: Fri, 28 Jun 2024 14:24:34 +0100 Subject: [PATCH 01/39] style fix: padding and radius of question bubble --- frontend/src/conversation/ConversationBubble.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/frontend/src/conversation/ConversationBubble.tsx b/frontend/src/conversation/ConversationBubble.tsx index 3a3842b2..3e515bf6 100644 --- a/frontend/src/conversation/ConversationBubble.tsx +++ b/frontend/src/conversation/ConversationBubble.tsx @@ -42,7 +42,7 @@ const ConversationBubble = forwardRef< bubble = (
-
+
{message} From d4375217109f4eea74e907ac99ef37268c9a043d Mon Sep 17 00:00:00 2001 From: utin-francis-peter Date: Fri, 28 Jun 2024 14:45:14 +0100 Subject: [PATCH 02/39] style fix: response bubble padding and radius --- frontend/src/conversation/ConversationBubble.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/frontend/src/conversation/ConversationBubble.tsx b/frontend/src/conversation/ConversationBubble.tsx index 3e515bf6..c82b5e69 100644 --- a/frontend/src/conversation/ConversationBubble.tsx +++ b/frontend/src/conversation/ConversationBubble.tsx @@ -68,7 +68,7 @@ const ConversationBubble = forwardRef< />
Date: Fri, 28 Jun 2024 15:16:55 +0100 Subject: [PATCH 03/39] style fix: gap between conversations wrapper and prompts input wrapper --- frontend/src/conversation/Conversation.tsx | 6 +++--- frontend/src/conversation/ConversationBubble.tsx | 2 +- frontend/src/index.css | 4 ++-- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/frontend/src/conversation/Conversation.tsx b/frontend/src/conversation/Conversation.tsx index 4fb34186..d9088153 100644 --- a/frontend/src/conversation/Conversation.tsx +++ b/frontend/src/conversation/Conversation.tsx @@ -191,11 +191,11 @@ export default function Conversation() { }; return ( -
+
{queries.length > 0 && !hasScrolledToLast && (
-
+
Date: Fri, 28 Jun 2024 20:19:01 +0100 Subject: [PATCH 04/39] style: spacings... --- frontend/src/Hero.tsx | 2 +- frontend/src/conversation/Conversation.tsx | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/frontend/src/Hero.tsx b/frontend/src/Hero.tsx index 904dd279..b74d22f2 100644 --- a/frontend/src/Hero.tsx +++ b/frontend/src/Hero.tsx @@ -19,7 +19,7 @@ export default function Hero({ }>; return (
diff --git a/frontend/src/conversation/Conversation.tsx b/frontend/src/conversation/Conversation.tsx index d9088153..964c5c8f 100644 --- a/frontend/src/conversation/Conversation.tsx +++ b/frontend/src/conversation/Conversation.tsx @@ -191,7 +191,7 @@ export default function Conversation() { }; return ( -
+
Date: Sat, 29 Jun 2024 18:55:10 +0100 Subject: [PATCH 05/39] style: updated custom css class to match textInput component's --- frontend/src/index.css | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/frontend/src/index.css b/frontend/src/index.css index 519b5f74..80a1aa8e 100644 --- a/frontend/src/index.css +++ b/frontend/src/index.css @@ -413,7 +413,7 @@ template { bottom: env(safe-area-inset-bottom, 0); } -.inputbox-style[contenteditable] { +.text-input { padding-left: 36px; padding-right: 36px; } From 522e966194d8d8de7f11b8789295ba04c508b790 Mon Sep 17 00:00:00 2001 From: utin-francis-peter Date: Sat, 29 Jun 2024 18:58:13 +0100 Subject: [PATCH 06/39] refactor: custom input component is used. inputRef is also replaced with state value --- frontend/src/conversation/Conversation.tsx | 36 +++++++++++++++++----- 1 file changed, 28 insertions(+), 8 deletions(-) diff --git a/frontend/src/conversation/Conversation.tsx b/frontend/src/conversation/Conversation.tsx index 4fb34186..ee85cbbd 100644 --- a/frontend/src/conversation/Conversation.tsx +++ b/frontend/src/conversation/Conversation.tsx @@ -20,12 +20,15 @@ import { sendFeedback } from './conversationApi'; import { useTranslation } from 'react-i18next'; import ArrowDown from './../assets/arrow-down.svg'; import RetryIcon from '../components/RetryIcon'; +import TextInput from '../components/inputs/TextInput'; export default function Conversation() { const queries = useSelector(selectQueries); const status = useSelector(selectStatus); const dispatch = useDispatch(); const endMessageRef = useRef(null); - const inputRef = useRef(null); + // const inputRef = useRef(null); + // migrating to useState for managing input values and onChange + const [prompt, setPrompt] = useState(''); const [isDarkTheme] = useDarkTheme(); const [hasScrolledToLast, setHasScrolledToLast] = useState(true); const fetchStream = useRef(null); @@ -112,14 +115,14 @@ export default function Conversation() { }; const handleQuestionSubmission = () => { - if (inputRef.current?.textContent && status !== 'loading') { + if (prompt.length && status !== 'loading') { if (lastQueryReturnedErr) { // update last failed query with new prompt dispatch( updateQuery({ index: queries.length - 1, query: { - prompt: inputRef.current.textContent, + prompt, }, }), ); @@ -128,9 +131,9 @@ export default function Conversation() { isRetry: true, }); } else { - handleQuestion({ question: inputRef.current.textContent }); + handleQuestion({ question: prompt }); } - inputRef.current.textContent = ''; + setPrompt(''); } }; @@ -190,6 +193,8 @@ export default function Conversation() { document.execCommand('insertText', false, text); }; + // console.log('inputRef: ', inputRef); + return (
-
{ if (e.key === 'Enter' && !e.shiftKey) { e.preventDefault(); handleQuestionSubmission(); } }} - >
+ >
*/} + setPrompt(e.target.value)} + placeholder={t('inputPlaceholder')} + onPaste={handlePaste} + onKeyDown={(e) => { + if (e.key === 'Enter' && !e.shiftKey) { + e.preventDefault(); + handleQuestionSubmission(); + } + }} + > {status === 'loading' ? ( Date: Sat, 29 Jun 2024 20:45:33 +0100 Subject: [PATCH 07/39] style: removed custom padding and used twClasses --- frontend/src/index.css | 5 ----- 1 file changed, 5 deletions(-) diff --git a/frontend/src/index.css b/frontend/src/index.css index 80a1aa8e..ac90fc66 100644 --- a/frontend/src/index.css +++ b/frontend/src/index.css @@ -412,8 +412,3 @@ template { .bottom-safe { bottom: env(safe-area-inset-bottom, 0); } - -.text-input { - padding-left: 36px; - padding-right: 36px; -} From 7408454a7566970815c7f37d612c7526ab3c56a4 Mon Sep 17 00:00:00 2001 From: utin-francis-peter Date: Mon, 1 Jul 2024 19:54:31 +0100 Subject: [PATCH 08/39] chore: prompts input now uses useState hook for state change and inbuilt autoFocus --- frontend/src/conversation/Conversation.tsx | 26 ---------------------- 1 file changed, 26 deletions(-) diff --git a/frontend/src/conversation/Conversation.tsx b/frontend/src/conversation/Conversation.tsx index ee85cbbd..96f1eecb 100644 --- a/frontend/src/conversation/Conversation.tsx +++ b/frontend/src/conversation/Conversation.tsx @@ -26,8 +26,6 @@ export default function Conversation() { const status = useSelector(selectStatus); const dispatch = useDispatch(); const endMessageRef = useRef(null); - // const inputRef = useRef(null); - // migrating to useState for managing input values and onChange const [prompt, setPrompt] = useState(''); const [isDarkTheme] = useDarkTheme(); const [hasScrolledToLast, setHasScrolledToLast] = useState(true); @@ -43,13 +41,6 @@ export default function Conversation() { !eventInterrupt && scrollIntoView(); }, [queries.length, queries[queries.length - 1]]); - useEffect(() => { - const element = document.getElementById('inputbox') as HTMLInputElement; - if (element) { - element.focus(); - } - }, []); - useEffect(() => { return () => { if (status !== 'idle') { @@ -241,25 +232,8 @@ export default function Conversation() {
- {/*
{ - if (e.key === 'Enter' && !e.shiftKey) { - e.preventDefault(); - handleQuestionSubmission(); - } - }} - >
*/} setPrompt(e.target.value)} placeholder={t('inputPlaceholder')} From d7b1310ba3681ed9b2975cccf1c4362ec4418517 Mon Sep 17 00:00:00 2001 From: FIRST_NAME LAST_NAME Date: Tue, 2 Jul 2024 22:11:21 +0530 Subject: [PATCH 09/39] conversation bubble width fix --- frontend/src/conversation/ConversationBubble.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/frontend/src/conversation/ConversationBubble.tsx b/frontend/src/conversation/ConversationBubble.tsx index 3a3842b2..29e51890 100644 --- a/frontend/src/conversation/ConversationBubble.tsx +++ b/frontend/src/conversation/ConversationBubble.tsx @@ -53,7 +53,7 @@ const ConversationBubble = forwardRef< bubble = (
Date: Tue, 2 Jul 2024 19:48:19 +0100 Subject: [PATCH 10/39] gap between y-borders and prompts input + border-radius reduction as prompts input grows --- frontend/src/conversation/Conversation.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/frontend/src/conversation/Conversation.tsx b/frontend/src/conversation/Conversation.tsx index 964c5c8f..487e8ea7 100644 --- a/frontend/src/conversation/Conversation.tsx +++ b/frontend/src/conversation/Conversation.tsx @@ -235,7 +235,7 @@ export default function Conversation() {
-
+
Date: Wed, 3 Jul 2024 13:25:47 +0530 Subject: [PATCH 11/39] fix: lint error - semantic ambiguity --- frontend/package-lock.json | 4 +++- frontend/package.json | 1 + frontend/src/upload/Upload.tsx | 8 ++++---- 3 files changed, 8 insertions(+), 5 deletions(-) diff --git a/frontend/package-lock.json b/frontend/package-lock.json index 295713e6..83e0a930 100644 --- a/frontend/package-lock.json +++ b/frontend/package-lock.json @@ -11,6 +11,7 @@ "@reduxjs/toolkit": "^1.9.2", "@vercel/analytics": "^0.1.10", "i18next": "^23.11.5", + "prop-types": "^15.8.1", "react": "^18.2.0", "react-copy-to-clipboard": "^5.1.0", "react-dom": "^18.2.0", @@ -1488,7 +1489,7 @@ "version": "18.0.10", "resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-18.0.10.tgz", "integrity": "sha512-E42GW/JA4Qv15wQdqJq8DL4JhNpB3prJgjgapN3qJT9K2zO5IIAQh4VXvCEDupoqAwnz0cY4RlXeC/ajX5SFHg==", - "devOptional": true, + "dev": true, "dependencies": { "@types/react": "*" } @@ -6606,6 +6607,7 @@ "version": "15.8.1", "resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.8.1.tgz", "integrity": "sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==", + "license": "MIT", "dependencies": { "loose-envify": "^1.4.0", "object-assign": "^4.1.1", diff --git a/frontend/package.json b/frontend/package.json index ebcbb3fe..5f7a11d8 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -22,6 +22,7 @@ "@reduxjs/toolkit": "^1.9.2", "@vercel/analytics": "^0.1.10", "i18next": "^23.11.5", + "prop-types": "^15.8.1", "react": "^18.2.0", "react-copy-to-clipboard": "^5.1.0", "react-dom": "^18.2.0", diff --git a/frontend/src/upload/Upload.tsx b/frontend/src/upload/Upload.tsx index 0360e2e5..2a1b51a9 100644 --- a/frontend/src/upload/Upload.tsx +++ b/frontend/src/upload/Upload.tsx @@ -55,7 +55,7 @@ function Upload({ } }, []); - function ProgressBar({ progress }: { progress: number }) { + function ProgressBar({ progressPercent }: { progressPercent: number }) { return (
- {progress >= 5 && `${progress}%`} + {progressPercent >= 5 && `${progressPercent}%`}
@@ -93,7 +93,7 @@ function Upload({ {/*

{progress?.percentage || 0}%

*/} {/* progress bar */} - + + )} + {isOpen && ( +
+ + + +
+ )}
)} + onDeleteConversation(conversation.id)} + submitLabel="Delete" + /> + {isShareModalOpen && conversationId && ( + { + setShareModalState(false); + }} + conversationId={conversationId} + /> + )}
); } diff --git a/frontend/src/modals/ShareConversationModal.tsx b/frontend/src/modals/ShareConversationModal.tsx new file mode 100644 index 00000000..886901b5 --- /dev/null +++ b/frontend/src/modals/ShareConversationModal.tsx @@ -0,0 +1,93 @@ +import { useState } from 'react'; +import { useTranslation } from 'react-i18next'; +import Spinner from '../assets/spinner.svg'; +import Exit from '../assets/exit.svg'; +const apiHost = import.meta.env.VITE_API_HOST || 'https://docsapi.arc53.com'; + +export const ShareConversationModal = ({ + close, + conversationId, +}: { + close: () => void; + conversationId: string; +}) => { + const [identifier, setIdentifier] = useState(null); + const [isCopied, setIsCopied] = useState(false); + type StatusType = 'loading' | 'idle' | 'fetched' | 'failed'; + const [status, setStatus] = useState('idle'); + const { t } = useTranslation(); + const domain = window.location.origin; + const handleCopyKey = (url: string) => { + navigator.clipboard.writeText(url); + setIsCopied(true); + }; + const shareCoversationPublicly: (isPromptable: boolean) => void = ( + isPromptable = false, + ) => { + setStatus('loading'); + fetch(`${apiHost}/api/share?isPromptable=${isPromptable}`, { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + }, + body: JSON.stringify({ conversation_id: conversationId }), + }) + .then((res) => { + console.log(res.status); + return res.json(); + }) + .then((data) => { + if (data.success && data.identifier) { + setIdentifier(data.identifier); + setStatus('fetched'); + } else setStatus('failed'); + }) + .catch((err) => setStatus('failed')); + }; + return ( +
+
+ +
+

Create a public page to share

+

+ Source document, personal information and further conversation will + remain private +

+
+ {`${domain}/shared/${ + identifier ?? '....' + }`} + {status === 'fetched' ? ( + + ) : ( + + )} +
+
+
+
+ ); +}; diff --git a/frontend/tailwind.config.cjs b/frontend/tailwind.config.cjs index 63f99513..938eacee 100644 --- a/frontend/tailwind.config.cjs +++ b/frontend/tailwind.config.cjs @@ -48,6 +48,7 @@ module.exports = { 'soap':'#D8CCF1', 'independence':'#54546D', 'philippine-yellow':'#FFC700', + 'bright-gray':'#EBEBEB' }, }, }, From 019bf013ac6990c8a7b2eb9e9ab256c014fbe0e1 Mon Sep 17 00:00:00 2001 From: ManishMadan2882 Date: Fri, 12 Jul 2024 02:51:59 +0530 Subject: [PATCH 29/39] add css class: no-scrollbar --- frontend/src/index.css | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/frontend/src/index.css b/frontend/src/index.css index c1d80714..7e0b3bda 100644 --- a/frontend/src/index.css +++ b/frontend/src/index.css @@ -22,6 +22,18 @@ background: #b1afaf; } +@layer utilities { + /* Chrome, Safari and Opera */ + .no-scrollbar::-webkit-scrollbar { + display: none; + } + + .no-scrollbar { + -ms-overflow-style: none; /* IE and Edge */ + scrollbar-width: none; /* Firefox */ + } +} + /*! normalize.css v8.0.1 | MIT License | github.com/necolas/normalize.css */ /* Document From 02187fed4e6ecc3156c111e31e39a9d916035c7a Mon Sep 17 00:00:00 2001 From: ManishMadan2882 Date: Sun, 14 Jul 2024 03:27:53 +0530 Subject: [PATCH 30/39] add timetamp in iso, remove sources --- application/api/user/routes.py | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/application/api/user/routes.py b/application/api/user/routes.py index 12744f0f..4b6bba8f 100644 --- a/application/api/user/routes.py +++ b/application/api/user/routes.py @@ -547,10 +547,15 @@ def get_publicly_shared_conversations(identifier : str): # Resolve the DBRef conversation_ref = shared['conversation_id'] conversation = db.dereference(conversation_ref) - conversation_queries = conversation['queries'][:(shared["first_n_queries"])] + if(conversation is None): + return jsonify({"sucess":False,"error":"might have broken url or the conversation does not exist"}),404 + conversation_queries = conversation['queries'][:(shared["first_n_queries"])] + for query in conversation_queries: + query.pop("sources") ## avoid exposing sources else: return jsonify({"sucess":False,"error":"might have broken url or the conversation does not exist"}),404 - return jsonify(conversation_queries),200 + date = conversation["_id"].generation_time.isoformat() + return jsonify({"success":True,"queries":conversation_queries,"title":conversation["name"],"timestamp":date}),200 except Exception as err: print (err) return jsonify({"success":False,"error":str(err)}),400 From 81d7fe3fdba409806a3620e51f315bc7fb816cf5 Mon Sep 17 00:00:00 2001 From: ManishMadan2882 Date: Sun, 14 Jul 2024 03:29:06 +0530 Subject: [PATCH 31/39] refactor App, add /shared/id page --- frontend/src/App.tsx | 87 +++++++++-- .../src/conversation/SharedConversation.tsx | 146 ++++++++++++++++++ frontend/src/hooks/index.ts | 14 +- .../src/modals/ShareConversationModal.tsx | 4 +- 4 files changed, 232 insertions(+), 19 deletions(-) create mode 100644 frontend/src/conversation/SharedConversation.tsx diff --git a/frontend/src/App.tsx b/frontend/src/App.tsx index 3083f1f3..2aa8a8fc 100644 --- a/frontend/src/App.tsx +++ b/frontend/src/App.tsx @@ -1,4 +1,5 @@ import { Routes, Route } from 'react-router-dom'; +import { ReactElement, useEffect } from 'react'; import Navigation from './Navigation'; import Conversation from './conversation/Conversation'; import About from './About'; @@ -8,29 +9,93 @@ import { useMediaQuery } from './hooks'; import { useState } from 'react'; import Setting from './settings'; import './locale/i18n'; - +import SharedConversation from './conversation/SharedConversation'; +import { useDarkTheme } from './hooks'; inject(); -export default function App() { +function MainLayout({ children }: { children: ReactElement }) { const { isMobile } = useMediaQuery(); const [navOpen, setNavOpen] = useState(!isMobile); return ( -
+ <>
- - } /> - } /> - } /> - } /> - + {children}
-
+ + ); +} + +function Layout({ children }: { children: ReactElement }) { + return ( + <> +
{children}
+ + ); +} +export default function App() { + const [isDarkTheme] = useDarkTheme(); + useEffect(() => { + localStorage.setItem('selectedTheme', isDarkTheme ? 'Dark' : 'Light'); + if (isDarkTheme) { + document + .getElementById('root') + ?.classList.add('dark', 'dark:bg-raisin-black'); + } else { + document.getElementById('root')?.classList.remove('dark'); + } + }, [isDarkTheme]); + return ( + <> + + + + + } + /> + + + + } + /> + + + + } + /> + + + + } + /> + {/* default page */} + + + + } + /> + + ); } diff --git a/frontend/src/conversation/SharedConversation.tsx b/frontend/src/conversation/SharedConversation.tsx new file mode 100644 index 00000000..82e6be62 --- /dev/null +++ b/frontend/src/conversation/SharedConversation.tsx @@ -0,0 +1,146 @@ +import { useState, useEffect } from 'react'; +import { useParams } from 'react-router-dom'; +import { useNavigate } from 'react-router-dom'; +import { Query } from './conversationModels'; +import ConversationBubble from './ConversationBubble'; +import { Fragment } from 'react'; +const apiHost = import.meta.env.VITE_API_HOST || 'https://docsapi.arc53.com'; +const SharedConversation = () => { + const params = useParams(); + const navigate = useNavigate(); + const { identifier } = params; //identifier is a uuid, not conversationId + const [queries, setQueries] = useState([]); + const [title, setTitle] = useState(''); + const [date, setDate] = useState(''); + + function formatISODate(isoDateStr: string) { + const date = new Date(isoDateStr); + + const monthNames = [ + 'Jan', + 'Feb', + 'Mar', + 'Apr', + 'May', + 'June', + 'July', + 'Aug', + 'Sept', + 'Oct', + 'Nov', + 'Dec', + ]; + + const month = monthNames[date.getMonth()]; + const day = date.getDate(); + const year = date.getFullYear(); + + let hours = date.getHours(); + const minutes = date.getMinutes(); + const ampm = hours >= 12 ? 'PM' : 'AM'; + + hours = hours % 12; + hours = hours ? hours : 12; + const minutesStr = minutes < 10 ? '0' + minutes : minutes; + const formattedDate = `Published ${month} ${day}, ${year} at ${hours}:${minutesStr} ${ampm}`; + return formattedDate; + } + const fetchQueris = () => { + fetch(`${apiHost}/api/shared_conversation/${identifier}`) + .then((res) => { + if (res.status === 404 || res.status === 400) navigate('/pagenotfound'); + return res.json(); + }) + .then((data) => { + if (data.success) { + setQueries(data.queries); + setTitle(data.title); + setDate(formatISODate(data.timestamp)); + } + }); + }; + + const prepResponseView = (query: Query, index: number) => { + let responseView; + if (query.response) { + responseView = ( + + ); + } else if (query.error) { + responseView = ( + + ); + } + return responseView; + }; + useEffect(() => { + fetchQueris(); + }, []); + return ( +
+
+ {queries.length > 0 && ( +
+
+
+

+ {title} +

+

+ Created with{' '} + + DocsGPT + +

+

+ {date} +

+
+
+ {queries.map((query, index) => { + return ( + + + + {prepResponseView(query, index)} + + ); + })} +
+
+
+ )} +
+ + + This is a chatbot that uses the GPT-3, Faiss and LangChain to answer + questions. + +
+
+
+ ); +}; + +export default SharedConversation; diff --git a/frontend/src/hooks/index.ts b/frontend/src/hooks/index.ts index 6248b3f8..c8258ad2 100644 --- a/frontend/src/hooks/index.ts +++ b/frontend/src/hooks/index.ts @@ -77,21 +77,23 @@ export function useDarkTheme() { // Set dark mode based on local storage preference if (savedMode === 'Dark') { setIsDarkTheme(true); - document.documentElement.classList.add('dark'); - document.documentElement.classList.add('dark:bg-raisin-black'); + document + .getElementById('root') + ?.classList.add('dark', 'dark:bg-raisin-black'); } else { // If no preference found, set to default (light mode) setIsDarkTheme(false); - document.documentElement.classList.remove('dark'); + document.getElementById('root')?.classList.remove('dark'); } }, []); useEffect(() => { localStorage.setItem('selectedTheme', isDarkTheme ? 'Dark' : 'Light'); if (isDarkTheme) { - document.documentElement.classList.add('dark'); - document.documentElement.classList.add('dark:bg-raisin-black'); + document + .getElementById('root') + ?.classList.add('dark', 'dark:bg-raisin-black'); } else { - document.documentElement.classList.remove('dark'); + document.getElementById('root')?.classList.remove('dark'); } }, [isDarkTheme]); //method to toggle theme diff --git a/frontend/src/modals/ShareConversationModal.tsx b/frontend/src/modals/ShareConversationModal.tsx index 886901b5..d32c5f90 100644 --- a/frontend/src/modals/ShareConversationModal.tsx +++ b/frontend/src/modals/ShareConversationModal.tsx @@ -57,13 +57,13 @@ export const ShareConversationModal = ({ remain private

- {`${domain}/shared/${ + {`${domain}/share/${ identifier ?? '....' }`} {status === 'fetched' ? (
)}
)} onDeleteConversation(conversation.id)} - submitLabel="Delete" + submitLabel={t('convTile.delete')} /> {isShareModalOpen && conversationId && ( { const [queries, setQueries] = useState([]); const [title, setTitle] = useState(''); const [date, setDate] = useState(''); - + const { t } = useTranslation(); function formatISODate(isoDateStr: string) { const date = new Date(isoDateStr); @@ -97,7 +98,7 @@ const SharedConversation = () => { {title}

- Created with{' '} + {t('sharedConv.subtitle')}{' '} DocsGPT @@ -131,11 +132,10 @@ const SharedConversation = () => { onClick={() => navigate('/')} className="w-fit rounded-full bg-purple-30 p-4 text-white shadow-xl transition-colors duration-200 hover:bg-purple-taupe" > - Get Started with DocsGPT + {t('sharedConv.button')} - This is a chatbot that uses the GPT-3, Faiss and LangChain to answer - questions. + {t('sharedConv.meta')}

diff --git a/frontend/src/locale/en.json b/frontend/src/locale/en.json index e59fbedc..e914693a 100644 --- a/frontend/src/locale/en.json +++ b/frontend/src/locale/en.json @@ -103,6 +103,22 @@ "deleteConv": { "confirm": "Are you sure you want to delete all the conversations?", "delete": "Delete" + }, + "shareConv": { + "label": "Create a public page to share", + "note": "Source document, personal information and further conversation will remain private", + "create": "Create" } + }, + "sharedConv": { + "subtitle": "Created with", + "button": "Get Started with DocsGPT", + "meta": "This is a chatbot that uses the GPT-3, Faiss and LangChain to answer questions." + }, + "convTile": { + "share": "Share", + "delete": "Delete", + "rename": "Rename", + "deleteWarning": "Are you sure you want to delete this conversation?" } } diff --git a/frontend/src/locale/es.json b/frontend/src/locale/es.json index 70966e4b..78a4aa29 100644 --- a/frontend/src/locale/es.json +++ b/frontend/src/locale/es.json @@ -103,6 +103,22 @@ "deleteConv": { "confirm": "¿Está seguro de que desea eliminar todas las conversaciones?", "delete": "Eliminar" + }, + "shareConv": { + "label": "Crear una página pública para compartir", + "note": "El documento original, la información personal y las conversaciones posteriores permanecerán privadas", + "create": "Crear" } + }, + "sharedConv": { + "subtitle": "Creado con", + "button": "Comienza con DocsGPT", + "meta": "Este es un chatbot que utiliza GPT-3, Faiss y LangChain para responder preguntas." + }, + "convTile": { + "share": "Compartir", + "delete": "Eliminar", + "rename": "Renombrar", + "deleteWarning": "¿Está seguro de que desea eliminar esta conversación?" } } diff --git a/frontend/src/locale/jp.json b/frontend/src/locale/jp.json index a025a17a..697b137f 100644 --- a/frontend/src/locale/jp.json +++ b/frontend/src/locale/jp.json @@ -103,6 +103,22 @@ "deleteConv": { "confirm": "すべての会話を削除してもよろしいですか?", "delete": "削除" + }, + "shareConv": { + "label": "共有ページを作成して共有する", + "note": "ソースドキュメント、個人情報、および以降の会話は非公開のままになります", + "create": "作成" } + }, + "sharedConv": { + "subtitle": "作成者", + "button": "DocsGPT を始める", + "meta": "GPT-3、Faiss、および LangChain を使用して質問に答えるチャットボットです" + }, + "convTile": { + "share": "共有", + "delete": "削除", + "rename": "名前変更", + "deleteWarning": "この会話を削除してもよろしいですか?" } } diff --git a/frontend/src/locale/zh.json b/frontend/src/locale/zh.json index f686ea20..8161f740 100644 --- a/frontend/src/locale/zh.json +++ b/frontend/src/locale/zh.json @@ -103,6 +103,22 @@ "deleteConv": { "confirm": "您确定要删除所有对话吗?", "delete": "删除" + }, + "shareConv": { + "label": "创建用于分享的公共页面", + "note": "源文档、个人信息和后续对话将保持私密", + "create": "创建" } + }, + "sharedConv": { + "subtitle": "使用创建", + "button": "开始使用 DocsGPT", + "meta": "这是一个使用 GPT-3、Faiss 和 LangChain 来回答问题的聊天机器人。" + }, + "convTile": { + "share": "分享", + "delete": "删除", + "rename": "重命名", + "deleteWarning": "您确定要删除此对话吗?" } } diff --git a/frontend/src/modals/ShareConversationModal.tsx b/frontend/src/modals/ShareConversationModal.tsx index d32c5f90..a6ab1e0f 100644 --- a/frontend/src/modals/ShareConversationModal.tsx +++ b/frontend/src/modals/ShareConversationModal.tsx @@ -51,11 +51,8 @@ export const ShareConversationModal = ({
-

Create a public page to share

-

- Source document, personal information and further conversation will - remain private -

+

{t('modals.shareConv.label')}

+

{t('modals.shareConv.note')}

{`${domain}/share/${ identifier ?? '....' @@ -76,7 +73,7 @@ export const ShareConversationModal = ({ shareCoversationPublicly(false); }} > - Create + {t('modals.shareConv.create')} {status === 'loading' && ( Date: Mon, 15 Jul 2024 02:55:38 +0530 Subject: [PATCH 33/39] feedback visible conditioned, update meta info in shared --- frontend/src/App.tsx | 6 +- .../src/conversation/ConversationBubble.tsx | 122 +++++++++--------- .../src/conversation/SharedConversation.tsx | 94 +++++++------- frontend/src/locale/en.json | 2 +- frontend/src/locale/es.json | 2 +- frontend/src/locale/jp.json | 2 +- frontend/src/locale/zh.json | 2 +- 7 files changed, 114 insertions(+), 116 deletions(-) diff --git a/frontend/src/App.tsx b/frontend/src/App.tsx index 2aa8a8fc..38694182 100644 --- a/frontend/src/App.tsx +++ b/frontend/src/App.tsx @@ -33,11 +33,7 @@ function MainLayout({ children }: { children: ReactElement }) { } function Layout({ children }: { children: ReactElement }) { - return ( - <> -
{children}
- - ); + return
{children}
; } export default function App() { const [isDarkTheme] = useDarkTheme(); diff --git a/frontend/src/conversation/ConversationBubble.tsx b/frontend/src/conversation/ConversationBubble.tsx index fc5d469e..4adfbf94 100644 --- a/frontend/src/conversation/ConversationBubble.tsx +++ b/frontend/src/conversation/ConversationBubble.tsx @@ -1,6 +1,6 @@ import { forwardRef, useState } from 'react'; import Avatar from '../components/Avatar'; -import CoppyButton from '../components/CopyButton'; +import CopyButton from '../components/CopyButton'; import remarkGfm from 'remark-gfm'; import { FEEDBACK, MESSAGE_TYPE } from './conversationModels'; import classes from './ConversationBubble.module.css'; @@ -103,7 +103,7 @@ const ConversationBubble = forwardRef< className={`absolute right-3 top-3 lg:invisible ${type !== 'ERROR' ? 'group-hover:lg:visible' : ''} `} > -
@@ -215,78 +215,82 @@ const ConversationBubble = forwardRef< ${type !== 'ERROR' ? 'group-hover:lg:visible' : ''}`} >
- +
-
-
+ {handleFeedback && ( + <>
- +
+ { - handleFeedback?.('LIKE'); - setIsLikeClicked(true); - setIsDislikeClicked(false); - }} - onMouseEnter={() => setIsLikeHovered(true)} - onMouseLeave={() => setIsLikeHovered(false)} - > + onClick={() => { + handleFeedback?.('LIKE'); + setIsLikeClicked(true); + setIsDislikeClicked(false); + }} + onMouseEnter={() => setIsLikeHovered(true)} + onMouseLeave={() => setIsLikeHovered(false)} + > +
+
-
-
-
-
- { - handleFeedback?.('DISLIKE'); - setIsDislikeClicked(true); - setIsLikeClicked(false); - }} - onMouseEnter={() => setIsDislikeHovered(true)} - onMouseLeave={() => setIsDislikeHovered(false)} - > +
+
+ { + handleFeedback?.('DISLIKE'); + setIsDislikeClicked(true); + setIsLikeClicked(false); + }} + onMouseEnter={() => setIsDislikeHovered(true)} + onMouseLeave={() => setIsDislikeHovered(false)} + > +
+
-
-
+ + )}
{sources && openSource !== null && sources[openSource] && ( diff --git a/frontend/src/conversation/SharedConversation.tsx b/frontend/src/conversation/SharedConversation.tsx index ff9ab3fb..1b9fb781 100644 --- a/frontend/src/conversation/SharedConversation.tsx +++ b/frontend/src/conversation/SharedConversation.tsx @@ -87,58 +87,56 @@ const SharedConversation = () => { useEffect(() => { fetchQueris(); }, []); - return ( -
-
- {queries.length > 0 && ( -
-
-
-

- {title} -

-

- {t('sharedConv.subtitle')}{' '} - - DocsGPT - -

-

- {date} -

-
-
- {queries.map((query, index) => { - return ( - - - {prepResponseView(query, index)} - - ); - })} -
-
+ return ( +
+
+
+
+

+ {title} +

+

+ {t('sharedConv.subtitle')}{' '} + + DocsGPT + +

+

+ {date} +

+
+
+ {queries?.map((query, index) => { + return ( + + + + {prepResponseView(query, index)} + + ); + })}
- )} -
- - - {t('sharedConv.meta')} -
+ +
+ + + {t('sharedConv.meta')} + +
); }; diff --git a/frontend/src/locale/en.json b/frontend/src/locale/en.json index e914693a..0f5aa708 100644 --- a/frontend/src/locale/en.json +++ b/frontend/src/locale/en.json @@ -113,7 +113,7 @@ "sharedConv": { "subtitle": "Created with", "button": "Get Started with DocsGPT", - "meta": "This is a chatbot that uses the GPT-3, Faiss and LangChain to answer questions." + "meta": "DocsGPT uses GenAI, please review critical information using sources." }, "convTile": { "share": "Share", diff --git a/frontend/src/locale/es.json b/frontend/src/locale/es.json index 78a4aa29..b91b67e9 100644 --- a/frontend/src/locale/es.json +++ b/frontend/src/locale/es.json @@ -113,7 +113,7 @@ "sharedConv": { "subtitle": "Creado con", "button": "Comienza con DocsGPT", - "meta": "Este es un chatbot que utiliza GPT-3, Faiss y LangChain para responder preguntas." + "meta": "DocsGPT utiliza GenAI, por favor revise la información crítica utilizando fuentes." }, "convTile": { "share": "Compartir", diff --git a/frontend/src/locale/jp.json b/frontend/src/locale/jp.json index 697b137f..75e62589 100644 --- a/frontend/src/locale/jp.json +++ b/frontend/src/locale/jp.json @@ -113,7 +113,7 @@ "sharedConv": { "subtitle": "作成者", "button": "DocsGPT を始める", - "meta": "GPT-3、Faiss、および LangChain を使用して質問に答えるチャットボットです" + "meta": "DocsGPT は GenAI を使用しています、情報源を使用して重要情報を確認してください。" }, "convTile": { "share": "共有", diff --git a/frontend/src/locale/zh.json b/frontend/src/locale/zh.json index 8161f740..e46fe254 100644 --- a/frontend/src/locale/zh.json +++ b/frontend/src/locale/zh.json @@ -113,7 +113,7 @@ "sharedConv": { "subtitle": "使用创建", "button": "开始使用 DocsGPT", - "meta": "这是一个使用 GPT-3、Faiss 和 LangChain 来回答问题的聊天机器人。" + "meta": "DocsGPT 使用 GenAI,请使用资源查看关键信息。" }, "convTile": { "share": "分享", From 7b8458b47de2cf708dac742e84972af0c582e39e Mon Sep 17 00:00:00 2001 From: ManishMadan2882 Date: Mon, 15 Jul 2024 05:00:13 +0530 Subject: [PATCH 34/39] fix layout --- frontend/src/App.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/frontend/src/App.tsx b/frontend/src/App.tsx index 38694182..dff27112 100644 --- a/frontend/src/App.tsx +++ b/frontend/src/App.tsx @@ -20,7 +20,7 @@ function MainLayout({ children }: { children: ReactElement }) { <>
Date: Mon, 15 Jul 2024 05:13:28 +0530 Subject: [PATCH 35/39] minor fix --- frontend/src/App.tsx | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/frontend/src/App.tsx b/frontend/src/App.tsx index dff27112..99a63cbc 100644 --- a/frontend/src/App.tsx +++ b/frontend/src/App.tsx @@ -17,10 +17,10 @@ function MainLayout({ children }: { children: ReactElement }) { const { isMobile } = useMediaQuery(); const [navOpen, setNavOpen] = useState(!isMobile); return ( - <> +
{children}
- +
); } From 1107a2f2bcdb2bff164b42d6cc8a42eb703662c6 Mon Sep 17 00:00:00 2001 From: ManishMadan2882 Date: Mon, 15 Jul 2024 17:56:23 +0530 Subject: [PATCH 36/39] refactor App.tsx: better convention --- frontend/src/App.tsx | 58 ++++--------------- frontend/src/PageNotFound.tsx | 6 +- .../src/conversation/SharedConversation.tsx | 2 +- 3 files changed, 15 insertions(+), 51 deletions(-) diff --git a/frontend/src/App.tsx b/frontend/src/App.tsx index 99a63cbc..05792187 100644 --- a/frontend/src/App.tsx +++ b/frontend/src/App.tsx @@ -1,5 +1,5 @@ import { Routes, Route } from 'react-router-dom'; -import { ReactElement, useEffect } from 'react'; +import { useEffect } from 'react'; import Navigation from './Navigation'; import Conversation from './conversation/Conversation'; import About from './About'; @@ -9,11 +9,12 @@ import { useMediaQuery } from './hooks'; import { useState } from 'react'; import Setting from './settings'; import './locale/i18n'; +import { Outlet } from 'react-router-dom'; import SharedConversation from './conversation/SharedConversation'; import { useDarkTheme } from './hooks'; inject(); -function MainLayout({ children }: { children: ReactElement }) { +function MainLayout() { const { isMobile } = useMediaQuery(); const [navOpen, setNavOpen] = useState(!isMobile); return ( @@ -26,15 +27,12 @@ function MainLayout({ children }: { children: ReactElement }) { : 'ml-0 md:ml-16' }`} > - {children} +
); } -function Layout({ children }: { children: ReactElement }) { - return
{children}
; -} export default function App() { const [isDarkTheme] = useDarkTheme(); useEffect(() => { @@ -50,47 +48,13 @@ export default function App() { return ( <> - - - - } - /> - - - - } - /> - - - - } - /> - - - - } - /> - {/* default page */} - - - - } - /> + }> + } /> + } /> + } /> + + } /> + } /> ); diff --git a/frontend/src/PageNotFound.tsx b/frontend/src/PageNotFound.tsx index eaea5cc9..0b86d7c1 100644 --- a/frontend/src/PageNotFound.tsx +++ b/frontend/src/PageNotFound.tsx @@ -2,11 +2,11 @@ import { Link } from 'react-router-dom'; export default function PageNotFound() { return ( -
-

+

+

404

The page you are looking for does not exist.

-

diff --git a/frontend/src/conversation/SharedConversation.tsx b/frontend/src/conversation/SharedConversation.tsx index 1b9fb781..e365c6f0 100644 --- a/frontend/src/conversation/SharedConversation.tsx +++ b/frontend/src/conversation/SharedConversation.tsx @@ -89,7 +89,7 @@ const SharedConversation = () => { }, []); return ( -
+
From e2b76d9c2963640a9a846f7dfe831c97d859ff1b Mon Sep 17 00:00:00 2001 From: ManishMadan2882 Date: Tue, 16 Jul 2024 02:09:36 +0530 Subject: [PATCH 37/39] feat(share): share btn above conversations --- frontend/src/conversation/Conversation.tsx | 31 +++++++++++++++++++ .../src/modals/ShareConversationModal.tsx | 2 +- 2 files changed, 32 insertions(+), 1 deletion(-) diff --git a/frontend/src/conversation/Conversation.tsx b/frontend/src/conversation/Conversation.tsx index 487e8ea7..115abcd8 100644 --- a/frontend/src/conversation/Conversation.tsx +++ b/frontend/src/conversation/Conversation.tsx @@ -11,6 +11,7 @@ import { selectStatus, updateQuery, } from './conversationSlice'; +import { selectConversationId } from '../preferences/preferenceSlice'; import Send from './../assets/send.svg'; import SendDark from './../assets/send_dark.svg'; import Spinner from './../assets/spinner.svg'; @@ -20,9 +21,13 @@ import { sendFeedback } from './conversationApi'; import { useTranslation } from 'react-i18next'; import ArrowDown from './../assets/arrow-down.svg'; import RetryIcon from '../components/RetryIcon'; +import ShareIcon from '../assets/share.svg'; +import { ShareConversationModal } from '../modals/ShareConversationModal'; + export default function Conversation() { const queries = useSelector(selectQueries); const status = useSelector(selectStatus); + const conversationId = useSelector(selectConversationId); const dispatch = useDispatch(); const endMessageRef = useRef(null); const inputRef = useRef(null); @@ -31,6 +36,7 @@ export default function Conversation() { const fetchStream = useRef(null); const [eventInterrupt, setEventInterrupt] = useState(false); const [lastQueryReturnedErr, setLastQueryReturnedErr] = useState(false); + const [isShareModalOpen, setShareModalState] = useState(false); const { t } = useTranslation(); const handleUserInterruption = () => { @@ -192,6 +198,31 @@ export default function Conversation() { return (
+ {conversationId && ( + <> + + {isShareModalOpen && ( + { + setShareModalState(false); + }} + conversationId={conversationId} + /> + )} + + )}
) : (