Fix SPA with routes and no context

This commit is contained in:
James Ketr 2025-05-05 13:27:41 -07:00
parent 170abae7c0
commit 406d1c1dc1
2 changed files with 62 additions and 36 deletions

View File

@ -39,6 +39,7 @@ import '@fontsource/roboto/700.css';
import MuiMarkdown from 'mui-markdown'; import MuiMarkdown from 'mui-markdown';
const getConnectionBase = (loc: any): string => { const getConnectionBase = (loc: any): string => {
console.log(`getConnectionBase(${loc})`)
if (!loc.host.match(/.*battle-linux.*/)) { if (!loc.host.match(/.*battle-linux.*/)) {
return loc.protocol + "//" + loc.host; return loc.protocol + "//" + loc.host;
} else { } else {
@ -46,6 +47,8 @@ const getConnectionBase = (loc: any): string => {
} }
} }
const connectionBase = getConnectionBase(window.location);
interface TabProps { interface TabProps {
label?: string, label?: string,
path: 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 App = () => {
const [sessionId, setSessionId] = useState<string | undefined>(undefined); const [sessionId, setSessionId] = useState<string | undefined>(undefined);
const [connectionBase,] = useState<string>(getConnectionBase(window.location))
const [menuOpen, setMenuOpen] = useState(false); const [menuOpen, setMenuOpen] = useState(false);
const [isMenuClosing, setIsMenuClosing] = useState(false); const [isMenuClosing, setIsMenuClosing] = useState(false);
const [activeTab, setActiveTab] = useState<number>(0); const [activeTab, setActiveTab] = useState<number>(0);
@ -272,51 +279,71 @@ const App = () => {
</Scrollable> </Scrollable>
) )
}]; }];
}, [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(() => { useEffect(() => {
const url = new URL(window.location.href); const url = new URL(window.location.href);
const pathParts = url.pathname.split('/').filter(Boolean); // [path, sessionId] const pathParts = url.pathname.split('/').filter(Boolean); // [path, sessionId]
console.log(tabs);
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");
}
};
if (pathParts.length < 1) { if (pathParts.length < 1) {
console.log("No session id or path -- creating new session"); console.log("No session id or path -- creating new session");
fetchSession(); fetchSession();
} else { } else {
const currentPath = pathParts.length < 2 ? '' : pathParts[0]; const currentPath = pathParts.length < 2 ? '' : pathParts[0];
const session = pathParts.length < 2 ? pathParts[0] : pathParts[1]; const path_session = pathParts.length < 2 ? pathParts[0] : pathParts[1];
let tabIndex = tabs.findIndex((tab) => tab.path === currentPath); if (!isValidUUIDv4(path_session)) {
if (-1 === tabIndex) { console.log(`Invalid session id ${path_session}-- creating new session`);
console.log(`Invalid path "${currentPath}" -- redirecting to default`); fetchSession(pathParts);
tabIndex = 0; } 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 = () => { const handleMenuClose = () => {
setIsMenuClosing(true); setIsMenuClosing(true);

View File

@ -20,7 +20,6 @@ const ChatQuery = (props : ChatQueryInterface) => {
if (typeof (tunables) === "string") { if (typeof (tunables) === "string") {
tunables = JSON.parse(tunables); tunables = JSON.parse(tunables);
} }
console.log(tunables);
if (submitQuery === undefined) { if (submitQuery === undefined) {
return (<Box>{prompt}</Box>); return (<Box>{prompt}</Box>);