From 1531a05de00b90351c067f0c378fe2c342b1f5a7 Mon Sep 17 00:00:00 2001 From: James Ketrenos Date: Mon, 9 Jun 2025 18:09:02 -0700 Subject: [PATCH] Pruned out React warnings --- frontend/src/config/navigationConfig.tsx | 19 +- frontend/src/pages/ResumeBuilderPage.css | 6 - frontend/src/pages/ResumeBuilderPage.tsx | 385 ---------------------- frontend/src/pages/candidate/Settings.tsx | 52 +-- frontend/src/routes/CandidateRoute.tsx | 4 +- frontend/src/services/api-client.ts | 29 -- 6 files changed, 31 insertions(+), 464 deletions(-) delete mode 100644 frontend/src/pages/ResumeBuilderPage.css delete mode 100644 frontend/src/pages/ResumeBuilderPage.tsx diff --git a/frontend/src/config/navigationConfig.tsx b/frontend/src/config/navigationConfig.tsx index c35fac6..e58db2c 100644 --- a/frontend/src/config/navigationConfig.tsx +++ b/frontend/src/config/navigationConfig.tsx @@ -8,31 +8,23 @@ import { BarChart as BarChartIcon, Settings as SettingsIcon, Work as WorkIcon, - Info as InfoIcon, Person as PersonIcon, Business as BusinessIcon, Quiz as QuizIcon, Analytics as AnalyticsIcon, Search as SearchIcon, Bookmark as BookmarkIcon, - History as HistoryIcon, - QuestionAnswer as QuestionAnswerIcon, - AttachMoney as AttachMoneyIcon, - BubbleChart, - InsertEmoticon, + BubbleChart, } from '@mui/icons-material'; import FaceRetouchingNaturalIcon from '@mui/icons-material/FaceRetouchingNatural'; import LibraryBooksIcon from '@mui/icons-material/LibraryBooks'; -import PersonSearchIcon from '@mui/icons-material/PersonSearch'; import { BackstoryLogo } from 'components/ui/BackstoryLogo'; import { HomePage } from 'pages/HomePage'; import { CandidateChatPage } from 'pages/CandidateChatPage'; -import { ResumeBuilderPage } from 'pages/ResumeBuilderPage'; import { DocsPage } from 'pages/DocsPage'; import { CreateProfilePage } from 'pages/CreateProfilePage'; import { VectorVisualizerPage } from 'pages/VectorVisualizerPage'; import { BetaPage } from 'pages/BetaPage'; -import { CandidateListingPage } from 'pages/FindCandidatePage'; import { JobAnalysisPage } from 'pages/JobAnalysisPage'; import { GenerateCandidate } from 'pages/GenerateCandidate'; import { Settings } from 'pages/candidate/Settings'; @@ -42,11 +34,8 @@ import { EmailVerificationPage } from 'components/EmailVerificationComponents'; import { Box, Typography } from '@mui/material'; import { NavigationConfig, NavigationItem } from 'types/navigation'; import { CandidateProfile } from 'pages/candidate/Profile'; -import { JobPicker } from 'components/ui/JobPicker'; import { DocumentManager } from 'components/DocumentManager'; import { VectorVisualizer } from 'components/VectorVisualizer'; -import { ComingSoon } from 'components/ui/ComingSoon'; -import { Beta } from 'components/ui/Beta'; // Beta page components for placeholder routes const SearchPage = () => (Search); @@ -68,16 +57,14 @@ export const navigationConfig: NavigationConfig = { { id: 'candidate-qa-setup', label: 'Q&A Setup', icon: , path: '/candidate/qa-setup', component: Candidate q&a setup page, userTypes: ['candidate'] }, { id: 'candidate-analytics', label: 'Analytics', icon: , path: '/candidate/analytics', component: Candidate analytics page, userTypes: ['candidate'] }, { id: 'candidate-job-analysis', label: 'Job Analysis', path: '/candidate/job-analysis', icon: , component: , userTypes: ['candidate'], }, - { id: 'candidate-resumes', label: 'Resumes', icon: , path: '/candidate/resumes', component: Candidate resumes page, userTypes: ['candidate'] }, - { id: 'candidate-resume-builder', label: 'Resume Builder', path: '/candidate/resume-builder', icon: , component: , userTypes: ['candidate'], }, + { id: 'candidate-resumes', label: 'Resumes', icon: , path: '/candidate/resumes', component: Candidate resumes page, userTypes: ['candidate'] }, { id: 'candidate-content', label: 'Content', icon: , path: '/candidate/content', component: , userTypes: ['candidate'] }, { id: 'candidate-settings', label: 'Settings', path: '/candidate/settings', icon: , component: , userTypes: ['candidate'], }, ], }, { id: 'employer-menu', label: 'Employer Tools', icon: , userTypes: ['employer'], children: [ - { id: 'employer-job-analysis', label: 'Job Analysis', path: '/employer/job-analysis', icon: , component: , userTypes: ['employer'], }, - { id: 'employer-resume-builder', label: 'Resume Builder', path: '/employer/resume-builder', icon: , component: , userTypes: ['employer'], }, + { id: 'employer-job-analysis', label: 'Job Analysis', path: '/employer/job-analysis', icon: , component: , userTypes: ['employer'], }, { id: 'employer-knowledge-explorer', label: 'Knowledge Explorer', path: '/employer/knowledge-explorer', icon: , component: , userTypes: ['employer'], }, { id: 'employer-search', label: 'Search', path: '/employer/search', icon: , component: , userTypes: ['employer'], }, { id: 'employer-saved', label: 'Saved', path: '/employer/saved', icon: , component: , userTypes: ['employer'], }, diff --git a/frontend/src/pages/ResumeBuilderPage.css b/frontend/src/pages/ResumeBuilderPage.css deleted file mode 100644 index 0f71ee9..0000000 --- a/frontend/src/pages/ResumeBuilderPage.css +++ /dev/null @@ -1,6 +0,0 @@ -.ResumeBuilder .JsonViewScrollable { - min-height: unset !important; - max-height: 30rem !important; - border: 1px solid orange; - overflow-x: auto !important; -} \ No newline at end of file diff --git a/frontend/src/pages/ResumeBuilderPage.tsx b/frontend/src/pages/ResumeBuilderPage.tsx deleted file mode 100644 index 85af5d0..0000000 --- a/frontend/src/pages/ResumeBuilderPage.tsx +++ /dev/null @@ -1,385 +0,0 @@ -import React, { useState, useCallback, useRef } from 'react'; -import { - Tabs, - Tab, - Box, -} from '@mui/material'; -import { SxProps } from '@mui/material'; - -import { BackstoryQuery } from 'components/BackstoryQuery'; -import { Conversation } from 'components/Conversation'; -import { BackstoryPageProps } from 'components/BackstoryTab'; -import { ChatQuery, ChatMessage } from "types/types"; -import './ResumeBuilderPage.css'; -import { useAppState } from 'hooks/GlobalContext'; - -/** - * ResumeBuilder component - * - * A responsive component that displays job descriptions, generated resumes and fact checks - * with different layouts for mobile and desktop views. - */ -const ResumeBuilderPage: React.FC = (props: BackstoryPageProps) => { - // State for editing job description - const [hasJobDescription, setHasJobDescription] = useState(false); - const [hasResume, setHasResume] = useState(false); - const [hasFacts, setHasFacts] = useState(false); - const jobConversationRef = useRef(null); - const resumeConversationRef = useRef(null); - const factsConversationRef = useRef(null); - - const [activeTab, setActiveTab] = useState(0); - - /** - * Handle tab change for mobile view - */ - const handleTabChange = (_event: React.SyntheticEvent, newValue: number): void => { - setActiveTab(newValue); - }; - - const handleJobQuery = (query: ChatQuery) => { - console.log(`handleJobQuery: ${query.prompt} -- `, jobConversationRef.current ? ' sending' : 'no handler'); - jobConversationRef.current?.submitQuery(query); - }; - - const handleResumeQuery = (query: ChatQuery) => { - console.log(`handleResumeQuery: ${query.prompt} -- `, resumeConversationRef.current ? ' sending' : 'no handler'); - resumeConversationRef.current?.submitQuery(query); - }; - - const handleFactsQuery = (query: ChatQuery) => { - console.log(`handleFactsQuery: ${query.prompt} -- `, factsConversationRef.current ? ' sending' : 'no handler'); - factsConversationRef.current?.submitQuery(query); - }; - - const filterJobDescriptionMessages = useCallback((messages: ChatMessage[]): ChatMessage[] => { - if (messages === undefined || messages.length === 0) { - return []; - } - - if (messages.length > 0) { - // messages[0].role = 'content'; - // messages[0].title = 'Job Description'; - // messages[0].disableCopy = false; - // messages[0].expandable = true; - } - - if (-1 !== messages.findIndex(m => m.status === 'done')) { // || (m.actions && m.actions.includes("resume_generated")))) { - setHasResume(true); - setHasFacts(true); - } - - return messages; - - if (messages.length > 1) { - setHasResume(true); - setHasFacts(true); - } - - - if (messages.length > 3) { - // messages[2] is Show job requirements - // messages[3].role = 'job-requirements'; - // messages[3].title = 'Job Requirements'; - // messages[3].disableCopy = false; - // messages[3].expanded = false; - // messages[3].expandable = true; - } - - /* Filter out the 2nd and 3rd (0-based) */ - const filtered = messages;//.filter((m, i) => i !== 1 && i !== 2); - console.warn("Set filtering back on"); - - return filtered; - }, [setHasResume, setHasFacts]); - - const filterResumeMessages = useCallback((messages: ChatMessage[]): ChatMessage[] => { - if (messages === undefined || messages.length === 0) { - return []; - } - - return messages; - - if (messages.length > 1) { - // messages[0] is Show Qualifications - // messages[1].role = 'qualifications'; - // messages[1].title = 'Candidate qualifications'; - // messages[1].disableCopy = false; - // messages[1].expanded = false; - // messages[1].expandable = true; - } - - if (messages.length > 3) { - // messages[2] is Show Resume - // messages[3].role = 'resume'; - // messages[3].title = 'Generated Resume'; - // messages[3].disableCopy = false; - // messages[3].expanded = true; - // messages[3].expandable = true; - } - - /* Filter out the 1st and 3rd messages (0-based) */ - const filtered = messages.filter((m, i) => i !== 0 && i !== 2); - - return filtered; - }, []); - - const filterFactsMessages = useCallback((messages: ChatMessage[]): ChatMessage[] => { - if (messages === undefined || messages.length === 0) { - return []; - } - - if (messages.length > 1) { - // messages[0] is Show verification - // messages[1].role = 'fact-check'; - // messages[1].title = 'Fact Check'; - // messages[1].disableCopy = false; - // messages[1].expanded = true; - // messages[1].expandable = true; - } - - /* Filter out the 1st (0-based) */ - const filtered = messages.filter((m, i) => i !== 0); - - return filtered; - }, []); - - const jobResponse = useCallback(async (message: ChatMessage) => { - // if (message.actions && message.actions.includes("job_description")) { - // if (jobConversationRef.current) { - // await jobConversationRef.current.fetchHistory(); - // } - // } - // if (message.actions && message.actions.includes("resume_generated")) { - // if (resumeConversationRef.current) { - // await resumeConversationRef.current.fetchHistory(); - // } - // setHasResume(true); - // setActiveTab(1); // Switch to Resume tab - // } - // if (message.actions && message.actions.includes("facts_checked")) { - // if (factsConversationRef.current) { - // await factsConversationRef.current.fetchHistory(); - // } - // setHasFacts(true); - // } - }, [setHasFacts, setHasResume, setActiveTab]); - - const resumeResponse = useCallback((message: ChatMessage): void => { - console.log('onResumeResponse', message); - setHasFacts(true); - }, [setHasFacts]); - - const factsResponse = useCallback((message: ChatMessage): void => { - console.log('onFactsResponse', message); - }, []); - - const resetJobDescription = useCallback(() => { - setHasJobDescription(false); - setHasResume(false); - setHasFacts(false); - }, [setHasJobDescription, setHasResume, setHasFacts]); - - const resetResume = useCallback(() => { - setHasResume(false); - setHasFacts(false); - }, [setHasResume, setHasFacts]); - - const resetFacts = useCallback(() => { - setHasFacts(false); - }, [setHasFacts]); - - return (Not re-implmented yet); - - -// const renderJobDescriptionView = useCallback((sx?: SxProps) => { -// console.log('renderJobDescriptionView'); -// const jobDescriptionQuestions = [ -// - // - // -// , -// ]; - - // const jobDescriptionPreamble: ChatMessage[] = [{ -// role: 'info', -// content: `Once you paste a job description and press **Generate Resume**, Backstory will perform the following actions: - -// 1. **Job Analysis**: LLM extracts requirements from '\`Job Description\`' to generate a list of desired '\`Skills\`'. -// 2. **Candidate Analysis**: LLM determines candidate qualifications by performing skill assessments. - -// For each '\`Skill\`' from **Job Analysis** phase: - -// 1. **RAG**: Retrieval Augmented Generation collection is queried for context related content for each '\`Skill\`'. -// 2. **Evidence Creation**: LLM is queried to generate supporting evidence of '\`Skill\`' from the '\`RAG\`' and '\`Candidate Resume\`'. -// 3. **Resume Generation**: LLM is provided the output from the **Candidate Analysis:Evidence Creation** phase and asked to generate a professional resume. - -// See [About > Resume Generation Architecture](/about/resume-generation) for more details. -// `, -// disableCopy: true -// }]; - - - // if (!hasJobDescription) { - // return - - // } else { - // return - // } - // }, [filterJobDescriptionMessages, hasJobDescription, sessionId, setSnack, jobResponse, resetJobDescription, hasFacts, hasResume, submitQuery]); - - // /** - // * Renders the resume view with loading indicator - // */ - // const renderResumeView = useCallback((sx?: SxProps) => { - // const resumeQuestions = [ - // - // - // - // , - // ]; - - // if (!hasFacts) { - // return - // } else { - // return - // } - // }, [filterResumeMessages, hasFacts, sessionId, setSnack, resumeResponse, resetResume, hasResume, submitQuery]); - - // /** - // * Renders the fact check view - // */ - // const renderFactCheckView = useCallback((sx?: SxProps) => { - // const factsQuestions = [ - // - // - // , - // ]; - - // return - // }, [ sessionId, setSnack, factsResponse, filterFactsMessages, resetFacts, hasResume, hasFacts, submitQuery]); - - // return ( - // - // {/* Tabs */} - // - // - // {hasResume && } - // {hasFacts && } - // - - // {/* Document display area */} - // - // {renderJobDescriptionView(/*{ height: "calc(100% - 72px - 48px)" }*/)} - // {renderResumeView(/*{ height: "calc(100% - 72px - 48px)" }*/)} - // {renderFactCheckView(/*{ height: "calc(100% - 72px - 48px)" }*/)} - // - // - // ); -}; - -export { - ResumeBuilderPage -}; - diff --git a/frontend/src/pages/candidate/Settings.tsx b/frontend/src/pages/candidate/Settings.tsx index 17d2a47..5bd9c36 100644 --- a/frontend/src/pages/candidate/Settings.tsx +++ b/frontend/src/pages/candidate/Settings.tsx @@ -19,20 +19,20 @@ import { useAppState } from 'hooks/GlobalContext'; import { useAuth } from 'hooks/AuthContext'; import * as Types from 'types/types'; -interface ServerTunables { - system_prompt: string, - tools: Tool[], - rags: Tool[] -}; +// interface ServerTunables { +// system_prompt: string, +// tools: Tool[], +// rags: Tool[] +// }; -type Tool = { - type: string, - enabled: boolean - name: string, - description: string, - parameters?: any, - returns?: any -}; +// type Tool = { +// type: string, +// enabled: boolean +// name: string, +// description: string, +// parameters?: any, +// returns?: any +// }; const SystemInfoComponent: React.FC<{ systemInfo: Types.SystemInfo | undefined }> = ({ systemInfo }) => { const [systemElements, setSystemElements] = useState([]); @@ -77,13 +77,13 @@ const SystemInfoComponent: React.FC<{ systemInfo: Types.SystemInfo | undefined } const Settings = (props: BackstoryPageProps) => { const { apiClient } = useAuth(); const { setSnack } = useAppState(); - const [editSystemPrompt, setEditSystemPrompt] = useState(""); + // const [editSystemPrompt, setEditSystemPrompt] = useState(""); const [systemInfo, setSystemInfo] = useState(undefined); - const [tools, setTools] = useState([]); - const [rags, setRags] = useState([]); - const [systemPrompt, setSystemPrompt] = useState(""); - const [messageHistoryLength, setMessageHistoryLength] = useState(5); - const [serverTunables, setServerTunables] = useState(undefined); + // const [tools, setTools] = useState([]); + // const [rags, setRags] = useState([]); + // const [systemPrompt, setSystemPrompt] = useState(""); + // const [messageHistoryLength, setMessageHistoryLength] = useState(5); + // const [serverTunables, setServerTunables] = useState(undefined); // useEffect(() => { // if (serverTunables === undefined || systemPrompt === serverTunables.system_prompt || !systemPrompt.trim()) { @@ -179,14 +179,14 @@ const Settings = (props: BackstoryPageProps) => { fetchSystemInfo(); - }, [systemInfo, setSystemInfo, setSnack]) + }, [systemInfo, setSystemInfo, setSnack, apiClient]); - useEffect(() => { - if (!systemPrompt) { - return; - } - setEditSystemPrompt(systemPrompt.trim()); - }, [systemPrompt, setEditSystemPrompt]); + // useEffect(() => { + // if (!systemPrompt) { + // return; + // } + // setEditSystemPrompt(systemPrompt.trim()); + // }, [systemPrompt, setEditSystemPrompt]); // const toggleRag = async (tool: Tool) => { // tool.enabled = !tool.enabled diff --git a/frontend/src/routes/CandidateRoute.tsx b/frontend/src/routes/CandidateRoute.tsx index c36f417..84f4296 100644 --- a/frontend/src/routes/CandidateRoute.tsx +++ b/frontend/src/routes/CandidateRoute.tsx @@ -1,4 +1,4 @@ -import React, { useEffect, useState } from "react"; +import React, { useEffect } from "react"; import { useParams, useNavigate } from "react-router-dom"; import { Box } from "@mui/material"; @@ -37,7 +37,7 @@ const CandidateRoute: React.FC = (props: CandidateRouteProp } getCandidate(username); - }, [selectedCandidate, username, selectedCandidate, navigate, setSnack, apiClient]); + }, [setSelectedCandidate, selectedCandidate, username, navigate, setSnack, apiClient]); if (selectedCandidate?.username !== username) { return ( diff --git a/frontend/src/services/api-client.ts b/frontend/src/services/api-client.ts index 2b69cca..464a69a 100644 --- a/frontend/src/services/api-client.ts +++ b/frontend/src/services/api-client.ts @@ -1210,35 +1210,6 @@ class ApiClient { return this.handleApiResponseWithConversion(response); } - /** - * Retry mechanism for rate-limited requests - */ - private async retryWithBackoff( - requestFn: () => Promise, - maxRetries: number = 3 - ): Promise { - let lastError: Error; - - for (let attempt = 0; attempt <= maxRetries; attempt++) { - try { - const response = await requestFn(); - return await this.handleApiResponseWithRateLimit(response); - } catch (error) { - lastError = error as Error; - - if (error instanceof RateLimitError && attempt < maxRetries) { - const delayMs = Math.min(error.retryAfterSeconds * 1000, 60000); // Max 1 minute - console.warn(`Rate limited, retrying in ${delayMs}ms (attempt ${attempt + 1}/${maxRetries + 1})`); - await new Promise(resolve => setTimeout(resolve, delayMs)); - continue; - } - - throw error; - } - } - - throw lastError!; - } async resetChatSession(id: string): Promise<{ success: boolean; message: string }> { const response = await fetch(`${this.baseUrl}/chat/sessions/${id}/reset`, { method: 'PATCH',