diff --git a/frontend/craco.config.js b/frontend/craco.config.js index eff42a6..0ac2a51 100644 --- a/frontend/craco.config.js +++ b/frontend/craco.config.js @@ -8,5 +8,16 @@ module.exports = { // key: '/path/to/key.pem', // } } - } -}; \ No newline at end of file + }, + webpack: { + configure: (webpackConfig) => { + // Add .ts and .tsx to resolve.extensions + webpackConfig.resolve.extensions = [ + ...webpackConfig.resolve.extensions, + '.ts', + '.tsx', + ]; + return webpackConfig; + }, + }, +}; diff --git a/frontend/public/disable-jpk.png b/frontend/public/disable-jpk.png deleted file mode 100755 index 826227c..0000000 Binary files a/frontend/public/disable-jpk.png and /dev/null differ diff --git a/frontend/public/partial-react-logo.png b/frontend/public/partial-react-logo.png deleted file mode 100755 index 66fd957..0000000 Binary files a/frontend/public/partial-react-logo.png and /dev/null differ diff --git a/frontend/public/react-logo.png b/frontend/public/react-logo.png deleted file mode 100755 index 9d72a9f..0000000 Binary files a/frontend/public/react-logo.png and /dev/null differ diff --git a/frontend/public/react-logo@2x.png b/frontend/public/react-logo@2x.png deleted file mode 100755 index 2229b13..0000000 Binary files a/frontend/public/react-logo@2x.png and /dev/null differ diff --git a/frontend/public/react-logo@3x.png b/frontend/public/react-logo@3x.png deleted file mode 100755 index a99b203..0000000 Binary files a/frontend/public/react-logo@3x.png and /dev/null differ diff --git a/frontend/public/settings.png b/frontend/public/settings.png deleted file mode 100755 index 8f7a3a9..0000000 Binary files a/frontend/public/settings.png and /dev/null differ diff --git a/frontend/public/splash-icon.png b/frontend/public/splash-icon.png deleted file mode 100755 index 03d6f6b..0000000 Binary files a/frontend/public/splash-icon.png and /dev/null differ diff --git a/frontend/src/App.tsx b/frontend/src/App.tsx index 7f503b7..fdaeaf2 100644 --- a/frontend/src/App.tsx +++ b/frontend/src/App.tsx @@ -1,8 +1,8 @@ import React, { useRef, useCallback } from 'react'; import { BrowserRouter as Router, Routes, Route, useLocation } from "react-router-dom"; -import { SessionWrapper } from "./SessionWrapper"; -import { Main } from "./Main"; -import { Snack, SeverityType } from './Snack'; +import { SessionWrapper } from "./App/SessionWrapper"; +import { Main } from "./App/Main"; +import { Snack, SeverityType } from './Components/Snack'; export function PathRouter({ setSnack }: { setSnack: any }) { const location = useLocation(); diff --git a/frontend/src/Main.css b/frontend/src/App/Main.css similarity index 100% rename from frontend/src/Main.css rename to frontend/src/App/Main.css diff --git a/frontend/src/Main.tsx b/frontend/src/App/Main.tsx similarity index 93% rename from frontend/src/Main.tsx rename to frontend/src/App/Main.tsx index 02e0c7a..f3c649a 100644 --- a/frontend/src/Main.tsx +++ b/frontend/src/App/Main.tsx @@ -16,21 +16,20 @@ import Box from '@mui/material/Box'; import CssBaseline from '@mui/material/CssBaseline'; import MenuIcon from '@mui/icons-material/Menu'; -import { ConversationHandle } from './Conversation'; -import { Query } from './ChatQuery'; -import { Scrollable } from './Scrollable'; -import { BackstoryPage, BackstoryTabProps } from './BackstoryTab'; +import { ConversationHandle } from '../Components/Conversation'; +import { Query } from '../Components/ChatQuery'; +import { Scrollable } from '../Components/Scrollable'; +import { BackstoryPage, BackstoryTabProps } from '../Components/BackstoryTab'; -import { HomePage } from './HomePage'; -import { LoadingPage } from './LoadingPage'; -import { ResumeBuilderPage } from './ResumeBuilderPage'; -import { VectorVisualizerPage } from './VectorVisualizer'; -import { AboutPage } from './AboutPage'; -import { ControlsPage } from './ControlsPage'; -import { SetSnackType } from './Snack'; +import { HomePage } from '../Pages/HomePage'; +import { LoadingPage } from '../Pages/LoadingPage'; +import { ResumeBuilderPage } from '../Pages/ResumeBuilderPage'; +import { VectorVisualizerPage } from '../Pages/VectorVisualizerPage'; +import { AboutPage } from '../Pages/AboutPage'; +import { ControlsPage } from '../Pages/ControlsPage'; +import { SetSnackType } from '../Components/Snack'; import './Main.css'; -import './Conversation.css'; import '@fontsource/roboto/300.css'; import '@fontsource/roboto/400.css'; diff --git a/frontend/src/SessionWrapper.tsx b/frontend/src/App/SessionWrapper.tsx similarity index 95% rename from frontend/src/SessionWrapper.tsx rename to frontend/src/App/SessionWrapper.tsx index 5ea4223..e9cca85 100644 --- a/frontend/src/SessionWrapper.tsx +++ b/frontend/src/App/SessionWrapper.tsx @@ -1,7 +1,7 @@ import { useEffect, useState, useRef } from "react"; import { useNavigate, useLocation } from "react-router-dom"; -import { connectionBase } from './Global'; -import { SetSnackType } from './Snack'; +import { connectionBase } from '../Global'; +import { SetSnackType } from '../Components/Snack'; const getSessionId = async () => { const response = await fetch(connectionBase + `/api/context`, { diff --git a/frontend/src/BackstoryTab.tsx b/frontend/src/Components/BackstoryTab.tsx similarity index 100% rename from frontend/src/BackstoryTab.tsx rename to frontend/src/Components/BackstoryTab.tsx diff --git a/frontend/src/BackstoryTextField.css b/frontend/src/Components/BackstoryTextField.css similarity index 100% rename from frontend/src/BackstoryTextField.css rename to frontend/src/Components/BackstoryTextField.css diff --git a/frontend/src/BackstoryTextField.tsx b/frontend/src/Components/BackstoryTextField.tsx similarity index 100% rename from frontend/src/BackstoryTextField.tsx rename to frontend/src/Components/BackstoryTextField.tsx diff --git a/frontend/src/ChatBubble.tsx b/frontend/src/Components/ChatBubble.tsx similarity index 100% rename from frontend/src/ChatBubble.tsx rename to frontend/src/Components/ChatBubble.tsx diff --git a/frontend/src/ChatQuery.tsx b/frontend/src/Components/ChatQuery.tsx similarity index 100% rename from frontend/src/ChatQuery.tsx rename to frontend/src/Components/ChatQuery.tsx diff --git a/frontend/src/ContextStatus.tsx b/frontend/src/Components/ContextStatus.tsx similarity index 100% rename from frontend/src/ContextStatus.tsx rename to frontend/src/Components/ContextStatus.tsx diff --git a/frontend/src/Conversation.css b/frontend/src/Components/Conversation.css similarity index 100% rename from frontend/src/Conversation.css rename to frontend/src/Components/Conversation.css diff --git a/frontend/src/Conversation.tsx b/frontend/src/Components/Conversation.tsx similarity index 99% rename from frontend/src/Conversation.tsx rename to frontend/src/Components/Conversation.tsx index 8c7a4c0..05ec724 100644 --- a/frontend/src/Conversation.tsx +++ b/frontend/src/Components/Conversation.tsx @@ -17,7 +17,7 @@ import { Query } from './ChatQuery'; import './Conversation.css'; import { BackstoryTextField, BackstoryTextFieldRef } from './BackstoryTextField'; import { BackstoryElementProps } from './BackstoryTab'; -import { connectionBase } from './Global'; +import { connectionBase } from '../Global'; const loadingMessage: BackstoryMessage = { "role": "status", "content": "Establishing connection with server..." }; diff --git a/frontend/src/CopyBubble.tsx b/frontend/src/Components/CopyBubble.tsx similarity index 100% rename from frontend/src/CopyBubble.tsx rename to frontend/src/Components/CopyBubble.tsx diff --git a/frontend/src/DeleteConfirmation.tsx b/frontend/src/Components/DeleteConfirmation.tsx similarity index 100% rename from frontend/src/DeleteConfirmation.tsx rename to frontend/src/Components/DeleteConfirmation.tsx diff --git a/frontend/src/Document.tsx b/frontend/src/Components/Document.tsx similarity index 100% rename from frontend/src/Document.tsx rename to frontend/src/Components/Document.tsx diff --git a/frontend/src/ExpandMore.tsx b/frontend/src/Components/ExpandMore.tsx similarity index 100% rename from frontend/src/ExpandMore.tsx rename to frontend/src/Components/ExpandMore.tsx diff --git a/frontend/src/Mermaid.tsx b/frontend/src/Components/Mermaid.tsx similarity index 100% rename from frontend/src/Mermaid.tsx rename to frontend/src/Components/Mermaid.tsx diff --git a/frontend/src/Message.tsx b/frontend/src/Components/Message.tsx similarity index 100% rename from frontend/src/Message.tsx rename to frontend/src/Components/Message.tsx diff --git a/frontend/src/Scrollable.tsx b/frontend/src/Components/Scrollable.tsx similarity index 100% rename from frontend/src/Scrollable.tsx rename to frontend/src/Components/Scrollable.tsx diff --git a/frontend/src/Snack.css b/frontend/src/Components/Snack.css similarity index 100% rename from frontend/src/Snack.css rename to frontend/src/Components/Snack.css diff --git a/frontend/src/Snack.tsx b/frontend/src/Components/Snack.tsx similarity index 100% rename from frontend/src/Snack.tsx rename to frontend/src/Components/Snack.tsx diff --git a/frontend/src/StyledMarkdown.css b/frontend/src/Components/StyledMarkdown.css similarity index 100% rename from frontend/src/StyledMarkdown.css rename to frontend/src/Components/StyledMarkdown.css diff --git a/frontend/src/StyledMarkdown.tsx b/frontend/src/Components/StyledMarkdown.tsx similarity index 100% rename from frontend/src/StyledMarkdown.tsx rename to frontend/src/Components/StyledMarkdown.tsx diff --git a/frontend/src/VectorVisualizer.css b/frontend/src/Components/VectorVisualizer.css similarity index 100% rename from frontend/src/VectorVisualizer.css rename to frontend/src/Components/VectorVisualizer.css diff --git a/frontend/src/VectorVisualizer.tsx b/frontend/src/Components/VectorVisualizer.tsx similarity index 95% rename from frontend/src/VectorVisualizer.tsx rename to frontend/src/Components/VectorVisualizer.tsx index 2945058..05b5c6c 100644 --- a/frontend/src/VectorVisualizer.tsx +++ b/frontend/src/Components/VectorVisualizer.tsx @@ -17,7 +17,7 @@ import TableContainer from '@mui/material/TableContainer'; import TableRow from '@mui/material/TableRow'; import { Scrollable } from './Scrollable'; -import { connectionBase } from './Global'; +import { connectionBase } from '../Global'; import './VectorVisualizer.css'; import { BackstoryPageProps } from './BackstoryTab'; @@ -66,14 +66,10 @@ interface PlotData { const config: Partial = { responsive: true, autosizable: true, - // displayModeBar: false, displaylogo: false, showSendToCloud: false, staticPlot: false, - //fillFrame: true, - /** if we DO autosize, set the frame margins in percents of plot size */ frameMargins: 0, - /** mousewheel or two-finger scroll zooms the plot */ scrollZoom: true, doubleClick: "reset+autosize", // | "lasso2d" @@ -119,7 +115,7 @@ const config: Partial = { }; const layout: Partial = { - autosize: true, + autosize: false, paper_bgcolor: '#FFFFFF', // white plot_bgcolor: '#FFFFFF', // white plot background font: { @@ -200,6 +196,22 @@ const VectorVisualizer: React.FC = (props: VectorVisualiz const [node, setNode] = useState(null); const theme = useTheme(); const isMobile = useMediaQuery(theme.breakpoints.down('md')); + const [plotDimensions, setPlotDimensions] = useState({ width: 0, height: 0 }); + + /* Force resize of Plotly as it tends to not be the correct size if it is initially rendered + * off screen (eg., the VectorVisualizer is not on the tab the app loads to) */ + useEffect(() => { + requestAnimationFrame(() => { + const plotContainer = document.querySelector('.plot-container') as HTMLElement; + const svgContainer = document?.querySelector('.svg-container') as HTMLElement; + if ( plotContainer && svgContainer) { + const plotContainerRect = plotContainer.getBoundingClientRect(); + svgContainer.style.width = `${plotContainerRect.width}px`; + svgContainer.style.height = `${plotContainerRect.height}px`; + setPlotDimensions({ width: plotContainerRect.width, height: plotContainerRect.height}); + } + }); + }); // Get the collection to visualize useEffect(() => { @@ -509,7 +521,7 @@ The scatter graph shows the query in N-dimensional space, mapped to ${view2D ? ' height: "100%", overflow: "hidden", }} - layout={layout} + layout={{...layout, width: plotDimensions.width, height: plotDimensions.height }} /> @@ -611,21 +623,8 @@ The scatter graph shows the query in N-dimensional space, mapped to ${view2D ? ' ); }; -const VectorVisualizerPage: React.FC = (props: VectorVisualizerProps) => { - return - - ; -}; - export type { VectorVisualizerProps }; export { VectorVisualizer, - VectorVisualizerPage }; diff --git a/frontend/src/useAutoScrollToBottom.tsx b/frontend/src/Components/useAutoScrollToBottom.tsx similarity index 100% rename from frontend/src/useAutoScrollToBottom.tsx rename to frontend/src/Components/useAutoScrollToBottom.tsx diff --git a/frontend/src/AboutPage.tsx b/frontend/src/Pages/AboutPage.tsx similarity index 93% rename from frontend/src/AboutPage.tsx rename to frontend/src/Pages/AboutPage.tsx index 28a8207..a107c80 100644 --- a/frontend/src/AboutPage.tsx +++ b/frontend/src/Pages/AboutPage.tsx @@ -1,8 +1,8 @@ import React, { useState, useEffect } from 'react'; -import { Scrollable } from './Scrollable'; -import { BackstoryPageProps } from './BackstoryTab'; -import { Document } from './Document'; +import { Scrollable } from '../Components/Scrollable'; +import { BackstoryPageProps } from '../Components/BackstoryTab'; +import { Document } from '../Components/Document'; const AboutPage = (props: BackstoryPageProps) => { const { sessionId, submitQuery, setSnack, route, setRoute } = props; diff --git a/frontend/src/ControlsPage.tsx b/frontend/src/Pages/ControlsPage.tsx similarity index 99% rename from frontend/src/ControlsPage.tsx rename to frontend/src/Pages/ControlsPage.tsx index 4e6b7ed..b961f64 100644 --- a/frontend/src/ControlsPage.tsx +++ b/frontend/src/Pages/ControlsPage.tsx @@ -14,9 +14,8 @@ import Typography from '@mui/material/Typography'; // import ResetIcon from '@mui/icons-material/History'; import ExpandMoreIcon from '@mui/icons-material/ExpandMore'; -import { connectionBase } from './Global'; -import { BackstoryPageProps } from './BackstoryTab'; -import { restyle } from 'plotly.js'; +import { connectionBase } from '../Global'; +import { BackstoryPageProps } from '../Components/BackstoryTab'; interface ServerTunables { system_prompt: string, diff --git a/frontend/src/HomePage.tsx b/frontend/src/Pages/HomePage.tsx similarity index 90% rename from frontend/src/HomePage.tsx rename to frontend/src/Pages/HomePage.tsx index 083fb34..c07daf9 100644 --- a/frontend/src/HomePage.tsx +++ b/frontend/src/Pages/HomePage.tsx @@ -4,10 +4,10 @@ import Box from '@mui/material/Box'; import { useTheme } from '@mui/material/styles'; import MuiMarkdown from 'mui-markdown'; -import { BackstoryPageProps } from './BackstoryTab'; -import { Conversation, ConversationHandle } from './Conversation'; -import { ChatQuery } from './ChatQuery'; -import { MessageList } from './Message'; +import { BackstoryPageProps } from '../Components//BackstoryTab'; +import { Conversation, ConversationHandle } from '../Components/Conversation'; +import { ChatQuery } from '../Components/ChatQuery'; +import { MessageList } from '../Components/Message'; const HomePage = forwardRef((props: BackstoryPageProps, ref) => { const { sessionId, setSnack, submitQuery } = props; diff --git a/frontend/src/LoadingPage.tsx b/frontend/src/Pages/LoadingPage.tsx similarity index 79% rename from frontend/src/LoadingPage.tsx rename to frontend/src/Pages/LoadingPage.tsx index 56a33ed..c768aed 100644 --- a/frontend/src/LoadingPage.tsx +++ b/frontend/src/Pages/LoadingPage.tsx @@ -1,6 +1,6 @@ import Box from '@mui/material/Box'; -import { BackstoryPageProps } from './BackstoryTab'; -import { BackstoryMessage, Message } from './Message'; +import { BackstoryPageProps } from '../Components/BackstoryTab'; +import { BackstoryMessage, Message } from '../Components/Message'; const LoadingPage = (props: BackstoryPageProps) => { const backstoryPreamble: BackstoryMessage = { diff --git a/frontend/src/ResumeBuilderPage.css b/frontend/src/Pages/ResumeBuilderPage.css similarity index 100% rename from frontend/src/ResumeBuilderPage.css rename to frontend/src/Pages/ResumeBuilderPage.css diff --git a/frontend/src/ResumeBuilderPage.tsx b/frontend/src/Pages/ResumeBuilderPage.tsx similarity index 98% rename from frontend/src/ResumeBuilderPage.tsx rename to frontend/src/Pages/ResumeBuilderPage.tsx index ffc8704..040398d 100644 --- a/frontend/src/ResumeBuilderPage.tsx +++ b/frontend/src/Pages/ResumeBuilderPage.tsx @@ -6,10 +6,10 @@ import { } from '@mui/material'; import { SxProps } from '@mui/material'; -import { ChatQuery, Query } from './ChatQuery'; -import { MessageList, BackstoryMessage } from './Message'; -import { Conversation } from './Conversation'; -import { BackstoryPageProps } from './BackstoryTab'; +import { ChatQuery, Query } from '../Components/ChatQuery'; +import { MessageList, BackstoryMessage } from '../Components/Message'; +import { Conversation } from '../Components/Conversation'; +import { BackstoryPageProps } from '../Components/BackstoryTab'; import './ResumeBuilderPage.css'; diff --git a/frontend/src/Pages/VectorVisualizerPage.tsx b/frontend/src/Pages/VectorVisualizerPage.tsx new file mode 100644 index 0000000..a471cc9 --- /dev/null +++ b/frontend/src/Pages/VectorVisualizerPage.tsx @@ -0,0 +1,28 @@ +import React, { useEffect, useState, useRef } from 'react'; + +import { Scrollable } from '../Components/Scrollable'; +import { VectorVisualizer } from '../Components/VectorVisualizer'; +import { BackstoryPageProps } from '../Components/BackstoryTab'; + +interface VectorVisualizerProps extends BackstoryPageProps { + inline?: boolean; + rag?: any; +}; + +const VectorVisualizerPage: React.FC = (props: VectorVisualizerProps) => { + return + + ; +}; + +export type { VectorVisualizerProps }; + +export { + VectorVisualizerPage +}; diff --git a/frontend/src/declarations.d.ts b/frontend/src/declarations.d.ts index 9b7fe5e..46ceee8 100644 --- a/frontend/src/declarations.d.ts +++ b/frontend/src/declarations.d.ts @@ -1,2 +1 @@ -declare module 'tsne-js'; declare module 'react-plotly.js'; \ No newline at end of file diff --git a/frontend/src/index.tsx b/frontend/src/index.tsx index dca0535..326144e 100644 --- a/frontend/src/index.tsx +++ b/frontend/src/index.tsx @@ -1,10 +1,9 @@ import React from 'react'; import ReactDOM from 'react-dom/client'; import { ThemeProvider } from '@mui/material/styles'; -import { backstoryTheme } from './BackstoryTheme'; // Adjust path as needed +import { backstoryTheme } from './BackstoryTheme'; import './index.css'; import App from './App'; -import reportWebVitals from './reportWebVitals'; const root = ReactDOM.createRoot( document.getElementById('root') as HTMLElement @@ -16,8 +15,3 @@ root.render( ); - -// If you want to start measuring performance in your app, pass a function -// to log results (for example: reportWebVitals(console.log)) -// or send to an analytics endpoint. Learn more: https://bit.ly/CRA-vitals -reportWebVitals(); diff --git a/frontend/src/reportWebVitals.ts b/frontend/src/reportWebVitals.ts deleted file mode 100644 index 49a2a16..0000000 --- a/frontend/src/reportWebVitals.ts +++ /dev/null @@ -1,15 +0,0 @@ -import { ReportHandler } from 'web-vitals'; - -const reportWebVitals = (onPerfEntry?: ReportHandler) => { - if (onPerfEntry && onPerfEntry instanceof Function) { - import('web-vitals').then(({ getCLS, getFID, getFCP, getLCP, getTTFB }) => { - getCLS(onPerfEntry); - getFID(onPerfEntry); - getFCP(onPerfEntry); - getLCP(onPerfEntry); - getTTFB(onPerfEntry); - }); - } -}; - -export default reportWebVitals; diff --git a/frontend/src/setupTests.ts b/frontend/src/setupTests.ts deleted file mode 100644 index 8f2609b..0000000 --- a/frontend/src/setupTests.ts +++ /dev/null @@ -1,5 +0,0 @@ -// jest-dom adds custom jest matchers for asserting on DOM nodes. -// allows you to do things like: -// expect(element).toHaveTextContent(/react/i) -// learn more: https://github.com/testing-library/jest-dom -import '@testing-library/jest-dom'; diff --git a/frontend/tsconfig.json b/frontend/tsconfig.json index a273b0c..e1f4257 100644 --- a/frontend/tsconfig.json +++ b/frontend/tsconfig.json @@ -18,9 +18,10 @@ "resolveJsonModule": true, "isolatedModules": true, "noEmit": true, - "jsx": "react-jsx" + "jsx": "react-jsx", + "baseUrl": "src", }, - "include": [ - "src" - ] +"include": [ + "src/**/*" +] } diff --git a/src/utils/check_serializable.py b/src/utils/check_serializable.py new file mode 100644 index 0000000..646066d --- /dev/null +++ b/src/utils/check_serializable.py @@ -0,0 +1,60 @@ +from pydantic import BaseModel, Field # type: ignore +import json +from typing import Any, List, Set + +def check_serializable(obj: Any, path: str = "", errors: List[str] = [], visited: Set[int] = set()) -> List[str]: + """ + Recursively check all fields in an object for non-JSON-serializable types, avoiding infinite recursion. + Skips fields in Pydantic models marked with Field(..., exclude=True). + Args: + obj: The object to inspect (Pydantic model, dict, list, or other). + path: The current field path (e.g., 'field1.nested_field'). + errors: List to collect error messages. + visited: Set of object IDs to track visited objects and prevent infinite recursion. + Returns: + List of error messages for non-serializable fields. + """ + # Check for circular reference by object ID + obj_id = id(obj) + if obj_id in visited: + errors.append(f"Field '{path}' contains a circular reference, skipping further inspection") + return errors + + # Add current object to visited set + visited.add(obj_id) + + try: + # Handle Pydantic models + if isinstance(obj, BaseModel): + for field_name, field_info in obj.model_fields.items(): + # Skip fields marked with exclude=True + if field_info.exclude: + continue + value = getattr(obj, field_name) + new_path = f"{path}.{field_name}" if path else field_name + check_serializable(value, new_path, errors, visited) + + # Handle dictionaries + elif isinstance(obj, dict): + for key, value in obj.items(): + new_path = f"{path}[{key}]" if path else str(key) + check_serializable(value, new_path, errors, visited) + + # Handle lists, tuples, or other iterables + elif isinstance(obj, (list, tuple)): + for i, value in enumerate(obj): + new_path = f"{path}[{i}]" if path else str(i) + check_serializable(value, new_path, errors, visited) + + # Handle other types (check for JSON serializability) + else: + try: + json.dumps(obj) + except (TypeError, OverflowError, ValueError) as e: + errors.append(f"Field '{path}' contains non-serializable type: {type(obj)} ({str(e)})") + + finally: + # Remove the current object from visited to allow processing in other branches + visited.discard(obj_id) + + return errors \ No newline at end of file