From 540d286d7ab3a366f498aa9ee255390f1a73cd7a Mon Sep 17 00:00:00 2001 From: James Ketrenos Date: Mon, 19 May 2025 12:24:09 -0700 Subject: [PATCH] Made changes to allow DNS from backstory-beta --- Dockerfile | 1 + docker-compose.yml | 2 + frontend/craco.config.js | 7 + frontend/package.json | 2 +- frontend/src/Components/Scrollable.tsx | 2 + frontend/src/Components/VectorVisualizer.css | 6 +- frontend/src/Components/VectorVisualizer.tsx | 27 +- frontend/src/NewApp/BackstoryApp.tsx | 53 +-- frontend/src/NewApp/Pages/AboutPage.tsx | 327 ++++++++++++++----- frontend/src/NewApp/Pages/HomePage.tsx | 68 +++- frontend/src/Pages/ResumeBuilderPage.tsx | 12 +- frontend/src/Pages/VectorVisualizerPage.css | 3 - frontend/src/Pages/VectorVisualizerPage.tsx | 11 +- frontend/src/index.css | 1 + 14 files changed, 358 insertions(+), 164 deletions(-) diff --git a/Dockerfile b/Dockerfile index 899189f..0fc7859 100644 --- a/Dockerfile +++ b/Dockerfile @@ -12,6 +12,7 @@ RUN apt-get update \ wget \ nano \ rsync \ + iputils-ping \ jq \ && apt-get clean \ && rm -rf /var/lib/apt/lists/{apt,dpkg,cache,log} diff --git a/docker-compose.yml b/docker-compose.yml index e712bb1..3304a94 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -78,6 +78,8 @@ services: - 3000:3000 # REACT expo while developing frontend volumes: - ./frontend:/opt/backstory/frontend:rw # Live mount frontend src + networks: + - internal ollama: build: diff --git a/frontend/craco.config.js b/frontend/craco.config.js index 0ac2a51..ce4b802 100644 --- a/frontend/craco.config.js +++ b/frontend/craco.config.js @@ -7,6 +7,13 @@ module.exports = { // cert: '/path/to/cert.pem', // key: '/path/to/key.pem', // } + }, + proxy: { + '/api': { + target: 'https://backstory:8911', // Replace with your FastAPI server URL + changeOrigin: true, + secure: false, // Set to true if your FastAPI server uses HTTPS + }, } }, webpack: { diff --git a/frontend/package.json b/frontend/package.json index 916ea25..a7ec2eb 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -41,7 +41,7 @@ "web-vitals": "^2.1.4" }, "scripts": { - "start": "HTTPS=true craco start", + "start": "HTTPS=true WDS_SOCKET_HOST=backstory-beta.ketrenos.com WDS_SOCKET_PORT=443 craco start", "build": "craco build", "test": "craco test" }, diff --git a/frontend/src/Components/Scrollable.tsx b/frontend/src/Components/Scrollable.tsx index b38ae6d..9f645e4 100644 --- a/frontend/src/Components/Scrollable.tsx +++ b/frontend/src/Components/Scrollable.tsx @@ -24,7 +24,9 @@ const Scrollable = (props: ScrollableProps) => { className={`Scrollable ${className || ""}`} sx={{ display: 'flex', + flexDirection: 'column', margin: '0 auto', + p: 0, flexGrow: 1, overflow: 'auto', // backgroundColor: '#F5F5F5', diff --git a/frontend/src/Components/VectorVisualizer.css b/frontend/src/Components/VectorVisualizer.css index e1f54f6..ce9ecdc 100644 --- a/frontend/src/Components/VectorVisualizer.css +++ b/frontend/src/Components/VectorVisualizer.css @@ -3,11 +3,7 @@ display: flex; flex-grow: 1; flex-direction: column; - background-color: #F5F5F5; - border: 1px solid #E0E0E0; font-size: 0.9rem; - margin: 0 auto; - padding: 10px; position: relative; - width: 100%; + max-width: 100%; } diff --git a/frontend/src/Components/VectorVisualizer.tsx b/frontend/src/Components/VectorVisualizer.tsx index df5eb34..8c5e89b 100644 --- a/frontend/src/Components/VectorVisualizer.tsx +++ b/frontend/src/Components/VectorVisualizer.tsx @@ -21,6 +21,7 @@ import { connectionBase } from '../Global'; import './VectorVisualizer.css'; import { BackstoryPageProps } from './BackstoryTab'; +import { relative } from 'path'; interface VectorVisualizerProps extends BackstoryPageProps { inline?: boolean; @@ -478,19 +479,13 @@ The scatter graph shows the query in N-dimensional space, mapped to ${view2D ? ' ...sx }}> - { - !inline && - - RAG Vector Visualization - - } @@ -528,20 +523,20 @@ The scatter graph shows the query in N-dimensional space, mapped to ${view2D ? ' {node !== null && - + - + Type {node.emoji} {node.doc_type} {node.source_file !== undefined && File - {node.source_file.replace(/^.*\//, '')}, lines: {node.line_begin}-{node.line_end} + {node.source_file.replace(/^.*\//, '')} } {node.path !== undefined && - Location + Section {node.path} } {node.distance !== undefined && @@ -560,7 +555,7 @@ The scatter graph shows the query in N-dimensional space, mapped to ${view2D ? ' } - + {node === null && Click a point in the scatter-graph to see information about that node. @@ -576,6 +571,8 @@ The scatter graph shows the query in N-dimensional space, mapped to ${view2D ? ' p: 0.5, pl: 1, flexShrink: 1, + position: "relative", + maxWidth: "100%", }} > { @@ -584,7 +581,7 @@ The scatter graph shows the query in N-dimensional space, mapped to ${view2D ? ' const bgColor = (index > node.line_begin && index <= node.line_end) ? '#f0f0f0' : 'auto'; return {index} -
{line || " "}
+
{line || " "}
; }) } diff --git a/frontend/src/NewApp/BackstoryApp.tsx b/frontend/src/NewApp/BackstoryApp.tsx index 52bbd5a..9e9645c 100644 --- a/frontend/src/NewApp/BackstoryApp.tsx +++ b/frontend/src/NewApp/BackstoryApp.tsx @@ -17,24 +17,30 @@ import BusinessIcon from '@mui/icons-material/Business'; import { SxProps, Theme } from '@mui/material'; import { ThemeProvider } from '@mui/material/styles'; +import { backstoryTheme } from '../BackstoryTheme'; + import {Header} from './Components/Header'; import { Scrollable } from '../Components/Scrollable'; import { Footer } from './Components/Footer'; -import { HomePage } from './Pages/HomePage'; -// import { BackstoryThemeVisualizer } from './BackstoryThemeVisualizer'; -import { HomePage as ChatPage } from '../Pages/HomePage'; -import { ResumeBuilderPage } from '../Pages/ResumeBuilderPage'; import { Snack, SeverityType } from '../Components/Snack'; import { Query } from '../Components/ChatQuery'; import { ConversationHandle } from '../Components/Conversation'; + + +import { HomePage } from './Pages/HomePage'; +import { HomePage as ChatPage } from '../Pages/HomePage'; +import { ResumeBuilderPage } from '../Pages/ResumeBuilderPage'; +// import { BackstoryThemeVisualizer } from './BackstoryThemeVisualizer'; import { AboutPage } from './Pages/AboutPage'; -import { backstoryTheme } from '../BackstoryTheme'; +import { BetaPage } from './Pages/BetaPage'; +import { CreateProfilePage } from './Pages/CreateProfilePage'; import '@fontsource/roboto/300.css'; import '@fontsource/roboto/400.css'; import '@fontsource/roboto/500.css'; import '@fontsource/roboto/700.css'; import { VectorVisualizerPage } from 'Pages/VectorVisualizerPage'; +import { calculatePoint } from 'mermaid/dist/utils'; type NavigationLinkType = { name: string; @@ -133,21 +139,18 @@ interface BackstoryPageContainerProps { const BackstoryPageContainer = (props : BackstoryPageContainerProps) => { const { children, sx } = props; return ( - - - - {children} - - - + + + {children} + + ); } const BackstoryApp = () => { @@ -187,6 +190,7 @@ const BackstoryApp = () => { flexDirection: 'column', backgroundColor: 'background.default', maxHeight: "calc(100vh - 72px)", + minHeight: "calc(100vh - 72px)", }}> @@ -195,6 +199,7 @@ const BackstoryApp = () => { } /> } /> } /> + } /> } /> }/> {/* Candidate-specific routes */} @@ -221,11 +226,11 @@ const BackstoryApp = () => { } /> } /> - {/* Redirect to dashboard by default */} - } /> - + {/* Redirect to BETA by default */} + } /> + + {location.pathname === "/" &&
} - { location.pathname === "/" &&
} diff --git a/frontend/src/NewApp/Pages/AboutPage.tsx b/frontend/src/NewApp/Pages/AboutPage.tsx index ba31146..a894130 100644 --- a/frontend/src/NewApp/Pages/AboutPage.tsx +++ b/frontend/src/NewApp/Pages/AboutPage.tsx @@ -1,24 +1,89 @@ import React, { useState, useEffect } from 'react'; -import {useNavigate, useLocation, useParams } from 'react-router-dom'; - -import { Box } from '@mui/material'; - -import { BackstoryPageProps } from '../../Components/BackstoryTab'; +import { useNavigate, useLocation, useParams } from 'react-router-dom'; +import { FileText, Code, Layers, Layout, Activity, Palette, Menu, X } from 'lucide-react'; import { Document } from '../../Components/Document'; -import { BackstoryUIOverviewPage} from './BackstoryUIOverviewPage'; +import { BackstoryPageProps } from '../../Components/BackstoryTab'; +import { BackstoryUIOverviewPage } from './BackstoryUIOverviewPage'; import { BackstoryAppAnalysisPage } from './BackstoryAppAnalysisPage'; import { BackstoryThemeVisualizerPage } from './BackstoryThemeVisualizerPage'; import { MockupPage } from './MockupPage'; +// Get appropriate icon for document type +const getDocumentIcon = (title: string) => { + switch (title) { + case 'About': + return ; + case 'BETA': + return ; + case 'Resume Generation Architecture': + case 'Application Architecture': + return ; + case 'UI Overview': + case 'UI Mockup': + return ; + case 'Theme Visualizer': + return ; + case 'App Analysis': + return ; + default: + return ; + } +}; + +// Sidebar navigation component with improved styling +const Sidebar: React.FC<{ + currentPage: string; + onDocumentSelect: (docName: string, open: boolean) => void; +}> = ({ currentPage, onDocumentSelect }) => { + // Document definitions + const documents = [ + { title: "About", route: "about" }, + { title: "BETA", route: "beta" }, + { title: "Resume Generation Architecture", route: "resume-generation" }, + { title: "Application Architecture", route: "about-app" }, + { title: "UI Overview", route: "ui-overview" }, + { title: "Theme Visualizer", route: "theme-visualizer" }, + { title: "App Analysis", route: "app-analysis" }, + { title: "UI Mockup", route: "ui-mockup" } + ]; + + return ( +
+

Documentation

+ +
+ ); +}; + +// AboutPage main component const AboutPage = (props: BackstoryPageProps) => { const { sessionId, submitQuery, setSnack } = props; const navigate = useNavigate(); const location = useLocation(); const { paramPage = '' } = useParams(); const [page, setPage] = useState(paramPage); + const [sidebarOpen, setSidebarOpen] = useState(true); - /* If the location changes, set the page based on the - * second part of the path, or clear if no path */ + // Track location changes useEffect(() => { const parts = location.pathname.split('/'); if (parts.length > 2) { @@ -28,6 +93,7 @@ const AboutPage = (props: BackstoryPageProps) => { } }, [location]); + // Handle document navigation const onDocumentExpand = (docName: string, open: boolean) => { console.log("Document expanded:", { docName, open, location }); if (open) { @@ -42,84 +108,173 @@ const AboutPage = (props: BackstoryPageProps) => { const basePath = location.pathname.split('/').slice(0, -1).join('/'); navigate(`${basePath}`); } - } + }; - return ( - { onDocumentExpand('about', open); }, - expanded: page === 'about', - sessionId, - submitQuery: submitQuery, - setSnack, - }} /> - { onDocumentExpand('beta', open); }, - expanded: page === 'beta', - sessionId, - submitQuery: submitQuery, - setSnack, - }} /> - { onDocumentExpand('resume-generation', open); }, - expanded: page === 'resume-generation', - sessionId, - submitQuery: submitQuery, - setSnack, - }} /> - { onDocumentExpand('about-app', open); }, - expanded: page === 'about-app', - sessionId, - submitQuery: submitQuery, - setSnack, - }} /> - , - onExpand: (open: boolean) => { onDocumentExpand('ui-overview', open); }, - expanded: page === 'ui-overview', - sessionId, - submitQuery: submitQuery, - setSnack, - }} /> - { onDocumentExpand('theme-visualizer', open); }, - expanded: page === 'theme-visualizer', - children: , - sessionId, - submitQuery: submitQuery, - setSnack, - }} /> - { onDocumentExpand('app-analysis', open); }, - expanded: page === 'app-analysis', - children: , - sessionId, - submitQuery: submitQuery, - setSnack, - }} /> - { onDocumentExpand('ui-mockup', open); }, - expanded: page === 'ui-mockup', - children: , - sessionId, - submitQuery: submitQuery, - setSnack, - }} /> - ) + // Toggle sidebar on mobile + const toggleSidebar = () => { + setSidebarOpen(!sidebarOpen); + }; + + return ( +
+ {/* Mobile Toggle Button */} + + +
+ {/* Sidebar - hidden on mobile when closed */} + {sidebarOpen && ( +
+ +
+ )} + + {/* Main Content Area */} +
+ {page === 'about' && ( + { onDocumentExpand('about', open); }} + expanded={page === 'about'} + sessionId={sessionId} + submitQuery={submitQuery} + setSnack={setSnack} + /> + )} + {page === 'beta' && ( + { onDocumentExpand('beta', open); }} + expanded={page === 'beta'} + sessionId={sessionId} + submitQuery={submitQuery} + setSnack={setSnack} + /> + )} + {page === 'resume-generation' && ( + { onDocumentExpand('resume-generation', open); }} + expanded={page === 'resume-generation'} + sessionId={sessionId} + submitQuery={submitQuery} + setSnack={setSnack} + /> + )} + {page === 'about-app' && ( + { onDocumentExpand('about-app', open); }} + expanded={page === 'about-app'} + sessionId={sessionId} + submitQuery={submitQuery} + setSnack={setSnack} + /> + )} + {page === 'ui-overview' && ( + } + onExpand={(open: boolean) => { onDocumentExpand('ui-overview', open); }} + expanded={page === 'ui-overview'} + sessionId={sessionId} + submitQuery={submitQuery} + setSnack={setSnack} + /> + )} + {page === 'theme-visualizer' && ( + { onDocumentExpand('theme-visualizer', open); }} + expanded={page === 'theme-visualizer'} + children={} + sessionId={sessionId} + submitQuery={submitQuery} + setSnack={setSnack} + /> + )} + {page === 'app-analysis' && ( + { onDocumentExpand('app-analysis', open); }} + expanded={page === 'app-analysis'} + children={} + sessionId={sessionId} + submitQuery={submitQuery} + setSnack={setSnack} + /> + )} + {page === 'ui-mockup' && ( + { onDocumentExpand('ui-mockup', open); }} + expanded={page === 'ui-mockup'} + children={} + sessionId={sessionId} + submitQuery={submitQuery} + setSnack={setSnack} + /> + )} + + {/* Show welcome grid if no specific page is selected */} + {!page && ( +
+

Documentation

+

+ Select a document from the sidebar to view detailed technical information about the application. +

+ +
+ {[ + { title: "About", route: "about", description: "General information about the application and its purpose" }, + { title: "BETA", route: "beta", description: "Details about the current beta version and upcoming features" }, + { title: "Resume Generation Architecture", route: "resume-generation", description: "Technical overview of how resumes are processed and generated" }, + { title: "Application Architecture", route: "about-app", description: "System design and technical stack information" }, + { title: "UI Overview", route: "ui-overview", description: "Guide to the user interface components and interactions" }, + { title: "Theme Visualizer", route: "theme-visualizer", description: "Explore and customize application themes and visual styles" }, + { title: "App Analysis", route: "app-analysis", description: "Statistics and performance metrics of the application" }, + { title: "UI Mockup", route: "ui-mockup", description: "Visual previews of interfaces and layout concepts" } + ].map((doc, index) => ( + + ))} +
+
+ )} +
+
+
+ ); }; -export { - AboutPage -}; \ No newline at end of file +export { AboutPage }; \ No newline at end of file diff --git a/frontend/src/NewApp/Pages/HomePage.tsx b/frontend/src/NewApp/Pages/HomePage.tsx index 84be5f0..e3525e9 100644 --- a/frontend/src/NewApp/Pages/HomePage.tsx +++ b/frontend/src/NewApp/Pages/HomePage.tsx @@ -1,7 +1,9 @@ import React from 'react'; +import { Navigate, Route, Routes, useLocation, useNavigate } from 'react-router-dom'; import { Box, Button, + ButtonProps, Container, Paper, Typography, @@ -37,17 +39,53 @@ const HeroSection = styled(Box)(({ theme }) => ({ }, })); -const HeroButton = styled(Button)(({ theme }) => ({ - marginTop: theme.spacing(2), - padding: theme.spacing(1, 3), - fontWeight: 500, - backgroundColor: theme.palette.action.active, - color: theme.palette.background.paper, - '&:hover': { +interface HeroButtonProps extends ButtonProps { + children?: string; +} +const HeroButton = (props: HeroButtonProps) => { + const { children, onClick, ...rest } = props; + + const navigate = useNavigate(); + + const handleClick = () => { + const path = children?.replace(/ /g, '-').toLocaleLowerCase() || '/'; + navigate(path); + }; + + const HeroStyledButton = styled(Button)(({ theme }) => ({ + marginTop: theme.spacing(2), + padding: theme.spacing(1, 3), + fontWeight: 500, backgroundColor: theme.palette.action.active, - opacity: 0.9, - }, -})); + color: theme.palette.background.paper, + '&:hover': { + backgroundColor: theme.palette.action.active, + opacity: 0.9, + }, + })); + return + {children} + +} + + +interface ActionButtonProps extends ButtonProps { + children?: string; +} +const ActionButton = (props: ActionButtonProps) => { + const { children, onClick, ...rest } = props; + + const navigate = useNavigate(); + + const handleClick = () => { + const path = children?.replace(/ /g, '-').toLocaleLowerCase() || '/'; + navigate(path); + }; + + return +} const FeatureIcon = styled(Box)(({ theme }) => ({ backgroundColor: theme.palette.action.active, @@ -95,6 +133,8 @@ const FeatureCard = ({ }; const HomePage = () => { + const navigate = useNavigate(); + return ( {/* Hero Section */} @@ -251,14 +291,14 @@ const HomePage = () => { - + @@ -339,14 +379,14 @@ const HomePage = () => { - + diff --git a/frontend/src/Pages/ResumeBuilderPage.tsx b/frontend/src/Pages/ResumeBuilderPage.tsx index 040398d..04d9d17 100644 --- a/frontend/src/Pages/ResumeBuilderPage.tsx +++ b/frontend/src/Pages/ResumeBuilderPage.tsx @@ -189,7 +189,7 @@ const ResumeBuilderPage: React.FC = (props: BackstoryPagePro setHasFacts(false); }, [setHasFacts]); - const renderJobDescriptionView = useCallback((sx: SxProps) => { + const renderJobDescriptionView = useCallback((sx?: SxProps) => { console.log('renderJobDescriptionView'); const jobDescriptionQuestions = [ @@ -262,7 +262,7 @@ See [About > Resume Generation Architecture](/about/resume-generation) for more /** * Renders the resume view with loading indicator */ - const renderResumeView = useCallback((sx: SxProps) => { + const renderResumeView = useCallback((sx?: SxProps) => { const resumeQuestions = [ @@ -311,7 +311,7 @@ See [About > Resume Generation Architecture](/about/resume-generation) for more /** * Renders the fact check view */ - const renderFactCheckView = useCallback((sx: SxProps) => { + const renderFactCheckView = useCallback((sx?: SxProps) => { const factsQuestions = [ @@ -368,9 +368,9 @@ See [About > Resume Generation Architecture](/about/resume-generation) for more display: 'flex', flexDirection: 'column', flexGrow: 1, p: 0, width: "100%", ...sx, overflow: "hidden" }}> - {renderJobDescriptionView({ height: "calc(100vh - 72px - 48px)" })} - {renderResumeView({ height: "calc(100vh - 72px - 48px)" })} - {renderFactCheckView({ height: "calc(100vh - 72px - 48px)" })} + {renderJobDescriptionView(/*{ height: "calc(100vh - 72px - 48px)" }*/)} + {renderResumeView(/*{ height: "calc(100vh - 72px - 48px)" }*/)} + {renderFactCheckView(/*{ height: "calc(100vh - 72px - 48px)" }*/)} ); diff --git a/frontend/src/Pages/VectorVisualizerPage.css b/frontend/src/Pages/VectorVisualizerPage.css index 988b2fe..a9cb33e 100644 --- a/frontend/src/Pages/VectorVisualizerPage.css +++ b/frontend/src/Pages/VectorVisualizerPage.css @@ -9,7 +9,4 @@ margin: 0 auto; padding: 10px; position: relative; - width: 100%; - max-width: 1024px; - height: calc(100vh - 72px); } diff --git a/frontend/src/Pages/VectorVisualizerPage.tsx b/frontend/src/Pages/VectorVisualizerPage.tsx index 9d638ec..1a025f4 100644 --- a/frontend/src/Pages/VectorVisualizerPage.tsx +++ b/frontend/src/Pages/VectorVisualizerPage.tsx @@ -1,6 +1,5 @@ import React from 'react'; -import { Scrollable } from '../Components/Scrollable'; import { VectorVisualizer } from '../Components/VectorVisualizer'; import { BackstoryPageProps } from '../Components/BackstoryTab'; @@ -12,15 +11,7 @@ interface VectorVisualizerProps extends BackstoryPageProps { }; const VectorVisualizerPage: React.FC = (props: VectorVisualizerProps) => { - return - - ; + return ; }; export type { VectorVisualizerProps }; diff --git a/frontend/src/index.css b/frontend/src/index.css index c629883..903d5e8 100644 --- a/frontend/src/index.css +++ b/frontend/src/index.css @@ -8,6 +8,7 @@ body { padding: 0; height: 100dvh; overflow: hidden; + min-width: 300px; } code {