From 406d1c1dc17a27dd8b2e4da27b7e790abc3533c6 Mon Sep 17 00:00:00 2001 From: James Ketrenos Date: Mon, 5 May 2025 13:27:41 -0700 Subject: [PATCH] Fix SPA with routes and no context --- frontend/src/App.tsx | 97 ++++++++++++++++++++++++-------------- frontend/src/ChatQuery.tsx | 1 - 2 files changed, 62 insertions(+), 36 deletions(-) diff --git a/frontend/src/App.tsx b/frontend/src/App.tsx index e504ae0..4ad84cf 100644 --- a/frontend/src/App.tsx +++ b/frontend/src/App.tsx @@ -39,6 +39,7 @@ import '@fontsource/roboto/700.css'; import MuiMarkdown from 'mui-markdown'; const getConnectionBase = (loc: any): string => { + console.log(`getConnectionBase(${loc})`) if (!loc.host.match(/.*battle-linux.*/)) { return loc.protocol + "//" + loc.host; } else { @@ -46,6 +47,8 @@ const getConnectionBase = (loc: any): string => { } } +const connectionBase = getConnectionBase(window.location); + interface TabProps { label?: string, path: string, @@ -57,9 +60,13 @@ interface TabProps { } }; +const isValidUUIDv4 = (str: string): boolean => { + const pattern = /^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-4[0-9a-fA-F]{3}-[89ab][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$/i; + return pattern.test(str); +} + const App = () => { const [sessionId, setSessionId] = useState(undefined); - const [connectionBase,] = useState(getConnectionBase(window.location)) const [menuOpen, setMenuOpen] = useState(false); const [isMenuClosing, setIsMenuClosing] = useState(false); const [activeTab, setActiveTab] = useState(0); @@ -272,51 +279,71 @@ const App = () => { ) }]; - }, [about, connectionBase, sessionId, setSnack, isMobile]); + }, [about, sessionId, setSnack, isMobile]); + + const fetchSession = useCallback((async (pathParts?: string[]) => { + + try { + const response = await fetch(connectionBase + `/api/context`, { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + }, + }); + + if (!response.ok) { + throw Error("Server is temporarily down."); + } + const new_session = (await response.json()).id; + console.log(`Session created: ${new_session}`); + + if (pathParts === undefined) { + setSessionId(new_session); + const newPath = `/${new_session}`; + window.history.replaceState({}, '', newPath); + } else { + const currentPath = pathParts.length < 2 ? '' : pathParts[0]; + let tabIndex = tabs.findIndex((tab) => tab.path === currentPath); + if (-1 === tabIndex) { + console.log(`Invalid path "${currentPath}" -- redirecting to default`); + window.history.replaceState({}, '', `/${new_session}`); + setActiveTab(0); + } else { + window.history.replaceState({}, '', `/${pathParts.join('/')}/${new_session}`); + setActiveTab(tabIndex); + } + setSessionId(new_session); + } + } catch (error: any) { + console.error(error); + setSnack("Server is temporarily down", "error"); + } + }), [setSnack, tabs]); useEffect(() => { const url = new URL(window.location.href); const pathParts = url.pathname.split('/').filter(Boolean); // [path, sessionId] - - const fetchSession = async () => { - try { - const response = await fetch(connectionBase + `/api/context`, { - method: 'POST', - headers: { - 'Content-Type': 'application/json', - }, - }); - - if (!response.ok) { - throw Error("Server is temporarily down."); - } - const data = await response.json(); - console.log(`Session created: ${data.id}`); - setSessionId(data.id); - - const newPath = `/${data.id}`; - window.history.replaceState({}, '', newPath); - } catch (error: any) { - console.error(error); - setSnack("Server is temporarily down", "error"); - } - }; - + console.log(tabs); if (pathParts.length < 1) { console.log("No session id or path -- creating new session"); fetchSession(); } else { const currentPath = pathParts.length < 2 ? '' : pathParts[0]; - const session = pathParts.length < 2 ? pathParts[0] : pathParts[1]; - let tabIndex = tabs.findIndex((tab) => tab.path === currentPath); - if (-1 === tabIndex) { - console.log(`Invalid path "${currentPath}" -- redirecting to default`); - tabIndex = 0; + const path_session = pathParts.length < 2 ? pathParts[0] : pathParts[1]; + if (!isValidUUIDv4(path_session)) { + console.log(`Invalid session id ${path_session}-- creating new session`); + fetchSession(pathParts); + } else { + let tabIndex = tabs.findIndex((tab) => tab.path === currentPath); + if (-1 === tabIndex) { + console.log(`Invalid path "${currentPath}" -- redirecting to default`); + tabIndex = 0; + } + setSessionId(path_session); + setActiveTab(tabIndex); } - setSessionId(session); - setActiveTab(tabIndex); } - }, [setSessionId, connectionBase, setSnack, tabs]); + }, [setSessionId, setSnack, tabs, fetchSession]); const handleMenuClose = () => { setIsMenuClosing(true); diff --git a/frontend/src/ChatQuery.tsx b/frontend/src/ChatQuery.tsx index 3ebe0ea..aefa348 100644 --- a/frontend/src/ChatQuery.tsx +++ b/frontend/src/ChatQuery.tsx @@ -20,7 +20,6 @@ const ChatQuery = (props : ChatQueryInterface) => { if (typeof (tunables) === "string") { tunables = JSON.parse(tunables); } - console.log(tunables); if (submitQuery === undefined) { return ({prompt});