From 81d7fe3fdba409806a3620e51f315bc7fb816cf5 Mon Sep 17 00:00:00 2001
From: ManishMadan2882
Date: Sun, 14 Jul 2024 03:29:06 +0530
Subject: [PATCH] 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' ? (