research mode and web image search removed

This commit is contained in:
shiva raj badu 2025-05-12 20:06:36 +05:45
parent 049c4ea01a
commit 19477e0919
7 changed files with 28 additions and 208 deletions

View file

@ -4,7 +4,7 @@ import path from "path"
export const localhost = "http://0.0.0.0"
export const isDev = !app.isPackaged;
export const isDev = false;
export const baseDir = app.getAppPath();
export const fastapiDir = isDev ? path.join(baseDir, "servers/fastapi") : path.join(baseDir, "resources/fastapi");
export const nextjsDir = isDev ? path.join(baseDir, "servers/nextjs") : path.join(baseDir, "resources/nextjs");

View file

@ -234,27 +234,7 @@ const ImageEditor = ({
}
};
const handleSearchImage = async () => {
const presentation_id = path.split("/")[2];
try {
setIsSearching(true);
setError(null);
const response = await PresentationGenerationApi.imageSearch({
presentation_id: presentation_id,
query: searchQuery,
page: 1,
limit: 20,
});
setSearchedImages(response.urls);
} catch (err) {
setError("Failed to fetch images. Please try again.");
} finally {
setIsSearching(false);
}
};
const handleFileUpload = async (
event: React.ChangeEvent<HTMLInputElement>
@ -527,13 +507,7 @@ const ImageEditor = ({
<TabsTrigger className="font-medium" value="generate">
AI Generate
</TabsTrigger>
<TabsTrigger
className="font-medium"
onClick={handleSearchImage}
value="search"
>
Web Images
</TabsTrigger>
<TabsTrigger className="font-medium" value="upload">
Upload
</TabsTrigger>
@ -599,58 +573,6 @@ const ImageEditor = ({
</div>
</div>
</TabsContent>
<TabsContent value="search" className="mt-4 space-y-4">
<form
onSubmit={(e) => {
e.preventDefault();
handleSearchImage();
}}
>
<div className="relative mb-3">
<Search className="absolute left-3 top-1/2 transform -translate-y-1/2 text-gray-500 w-4 h-4" />
<Input
placeholder="Search images..."
value={searchQuery}
onChange={(e) => setSearchQuery(e.target.value)}
className="pl-10"
/>
</div>
<Button
type="submit"
variant="outline"
className="w-full text-semibold text-[#51459e]"
>
Search
</Button>
</form>
{error && <p className="text-red-500 text-sm">{error}</p>}
<div className="grid grid-cols-2 gap-4 max-h-[80vh] hide-scrollbar overflow-y-auto">
{isSearching
? Array.from({ length: 6 }).map((_, index) => (
<Skeleton
key={index}
className="aspect-[4/3] w-full rounded-lg"
/>
))
: searchedImages.map((imgSrc, index) => (
<div
key={index}
onClick={() => handleImageChange(imgSrc)}
className="aspect-[4/3] cursor-pointer group relative rounded-lg overflow-hidden"
>
<img
src={imgSrc}
alt={`Search result ${index + 1}`}
className="w-full h-full object-cover group-hover:scale-105 transition-transform"
/>
<div className="absolute inset-0 bg-black/0 group-hover:bg-black/20 transition-all duration-200" />
</div>
))}
</div>
</TabsContent>
<TabsContent value="upload" className="mt-4 space-y-4">
<div className="space-y-4">
<div

View file

@ -51,7 +51,7 @@ const DocumentsPreviewPage: React.FC = () => {
const textareaRef = useRef<HTMLTextAreaElement>(null);
// Redux state
const { config, reports, documents, images, charts, tables } = useSelector(
const { config, documents, images, charts, tables } = useSelector(
(state: RootState) => state.pptGenUpload
);
@ -68,10 +68,9 @@ const DocumentsPreviewPage: React.FC = () => {
});
// Memoized values
const reportKeys = useMemo(() => Object.keys(reports), [reports]);
const documentKeys = useMemo(() => Object.keys(documents), [documents]);
const imageKeys = useMemo(() => Object.keys(images), [images]);
const allSources = useMemo(() => [...reportKeys, ...documentKeys, ...imageKeys], [reportKeys, documentKeys, imageKeys]);
const allSources = useMemo(() => [...documentKeys, ...imageKeys], [documentKeys, imageKeys]);
@ -96,14 +95,7 @@ const DocumentsPreviewPage: React.FC = () => {
}
});
// Process reports
reportKeys.forEach(key => {
if (!(key in textContents)) {
newDocuments.push(key);
// @ts-ignore
promises.push(window.electron.readFile(reports[key]));
}
});
if (promises.length > 0) {
setDownloadingDocuments(newDocuments);
@ -148,13 +140,11 @@ const DocumentsPreviewPage: React.FC = () => {
});
const documentPaths = documentKeys.map(key => documents[key]);
const researchReportPath = reports['research_report_content'];
const createResponse = await PresentationGenerationApi.getQuestions({
prompt: config?.prompt ?? "",
n_slides: config?.slides ? parseInt(config.slides) : null,
documents: documentPaths,
images: imageKeys,
research_reports: researchReportPath ? [researchReportPath] : [],
language: config?.language ?? "",
});
@ -219,10 +209,9 @@ const DocumentsPreviewPage: React.FC = () => {
if (!selectedDocument) return null;
const isDocument = documentKeys.includes(selectedDocument);
const isReport = reportKeys.includes(selectedDocument);
const hasTablesAndCharts = documentTablesAndCharts().length > 0;
if (!isDocument && !isReport) return null;
if (!isDocument) return null;
return (
<div className="h-full mr-4">
@ -271,24 +260,7 @@ const DocumentsPreviewPage: React.FC = () => {
size={20}
/>
{reportKeys.length > 0 && (
<div
onClick={() => updateSelectedDocument(reportKeys[0])}
className={`${selectedDocument === reportKeys[0]
? styles.selected_border
: styles.unselected_border
} ${styles.report_icon_box} flex justify-center items-center rounded-lg w-full h-32 cursor-pointer`}
>
<div>
<img
className="mx-auto h-20"
src="/report.png"
alt="Research Report"
/>
<p className="text-sm mt-2 text-[#2E2E2E]">Research Report</p>
</div>
</div>
)}
{documentKeys.length > 0 && (
<div className="mt-8">

View file

@ -64,34 +64,7 @@ export class PresentationGenerationApi {
}
}
static async generateResearchReport(prompt: string, language: string | null) {
const apiBody = {
query: prompt,
language: language,
};
try {
const response = await fetch(
`${BASE_URL}/ppt/report/generate`,
{
method: "POST",
headers: getHeader(),
body: JSON.stringify(apiBody),
cache: "no-cache",
}
);
if (response.status === 200) {
const data = await response.json();
return data;
} else {
throw new Error(`Failed to generate report: ${response.statusText}`);
}
} catch (error) {
console.error("Error in Generate Research Report", error);
throw error;
}
}
static async decomposeDocuments(documentKeys: string[], imageKeys: string[]) {
try {
@ -452,7 +425,6 @@ export class PresentationGenerationApi {
n_slides,
documents,
images,
research_reports,
language,
}: {
@ -460,7 +432,6 @@ export class PresentationGenerationApi {
n_slides: number | null;
documents?: string[];
images?: string[];
research_reports?: string[];
language: string | null;
}) {
@ -475,7 +446,6 @@ export class PresentationGenerationApi {
n_slides,
language,
documents,
research_reports,
images,
}),

View file

@ -1,20 +1,17 @@
import { Textarea } from "@/components/ui/textarea";
import { useState } from "react";
import * as Switch from "@radix-ui/react-switch";
import styles from "../styles/main.module.css";
interface PromptInputProps {
value: string;
onChange: (value: string) => void;
researchMode: boolean;
setResearchMode: (value: boolean) => void;
}
export function PromptInput({
value,
onChange,
researchMode,
setResearchMode,
}: PromptInputProps) {
const [showHint, setShowHint] = useState(false);
const handleChange = (value: string) => {
@ -23,33 +20,7 @@ export function PromptInput({
};
return (
<div className="space-y-2">
<div className="flex justify-between">
<h4 className=" font-instrument_sans text-lg text-[#444] font-medium ">
Prompt
</h4>
<div className="flex justify-end">
<div
className={`inline-flex items-center gap-2 px-3 py-1.5 rounded-md border border-[#5146E5] text-sm font-semibold ${researchMode ? "bg-[#5146E5] text-white" : "text-[#5146E5]"
}`}
>
<span>Research Mode</span>
<Switch.Root
defaultChecked={researchMode}
onCheckedChange={(val) => setResearchMode(val)}
className={`${styles.SwitchRoot}`}
data-testid="research-mode-switch"
>
<Switch.Thumb className={styles.SwitchThumb} />
</Switch.Root>
</div>
</div>
</div>
{researchMode && (
<p className="bg-blue-100 border font-instrument_sans text-sm md:text-base transition-all duration-300 border-blue-200 p-2 text-center rounded-md ">
Research mode searches the web to gather the latest information based
on your prompt and documents.
</p>
)}
<div className="relative">
<Textarea
@ -58,8 +29,7 @@ export function PromptInput({
onChange={(e) => handleChange(e.target.value)}
placeholder="Tell us about your presentation"
data-testid="prompt-input"
className={`py-4 px-5 border-2 font-medium font-instrument_sans text-base min-h-[150px] max-h-[300px] border-[#5146E5] focus-visible:ring-offset-0 focus-visible:ring-[#5146E5] overflow-y-auto custom_scrollbar ${researchMode ? "border-dashed" : ""
}`}
className={`py-4 px-5 border-2 font-medium font-instrument_sans text-base min-h-[150px] max-h-[300px] border-[#5146E5] focus-visible:ring-offset-0 focus-visible:ring-[#5146E5] overflow-y-auto custom_scrollbar `}
/>
</div>

View file

@ -5,7 +5,7 @@
* - Configure presentation settings (slides, language)
* - Input prompts
* - Upload supporting documents and images
* - Generate presentations with or without research mode
*
* @component
*/
@ -51,7 +51,6 @@ interface DecomposedResponse {
interface ProcessedData {
config: PresentationConfig;
reports: Record<string, string>;
documents: Record<string, any>;
images: Record<string, any>;
charts: Record<string, any>;
@ -65,7 +64,6 @@ const UploadPage = () => {
const { toast } = useToast();
// State management
const [researchMode, setResearchModel] = useState<boolean>(false);
const [documents, setDocuments] = useState<File[]>([]);
const [images, setImages] = useState<File[]>([]);
const [config, setConfig] = useState<PresentationConfig>({
@ -142,8 +140,8 @@ const UploadPage = () => {
try {
const hasUploadedAssets = documents.length > 0 || images.length > 0;
if (researchMode || hasUploadedAssets) {
await handleResearchAndDocumentProcessing();
if (hasUploadedAssets) {
await handleDocumentProcessing();
} else {
await handleDirectPresentationGeneration();
}
@ -153,14 +151,14 @@ const UploadPage = () => {
};
/**
* Handles research mode and document processing
* Handles document processing
*/
const handleResearchAndDocumentProcessing = async () => {
const handleDocumentProcessing = async () => {
setLoadingState({
isLoading: true,
message: researchMode ? "Creating research report..." : "Processing documents...",
message: "Processing documents...",
showProgress: true,
duration: researchMode ? 80 : 90,
duration: 90,
extra_info: documents.length > 0 ? "It might take a few minutes for large documents." : "",
});
@ -174,11 +172,7 @@ const UploadPage = () => {
}
const promises: Promise<any>[] = [];
if (researchMode) {
promises.push(
PresentationGenerationApi.generateResearchReport(config.prompt, config.language)
);
}
if (documents.length > 0 || images.length > 0) {
promises.push(
PresentationGenerationApi.decomposeDocuments(documentKeys, imageKeys)
@ -187,7 +181,7 @@ const UploadPage = () => {
const responses = await Promise.all(promises);
const processedData = processApiResponses(responses, researchMode);
const processedData = processApiResponses(responses);
dispatch(setPptGenUploadState(processedData));
router.push("/documents-preview");
@ -196,21 +190,15 @@ const UploadPage = () => {
/**
* Processes API responses and formats data for state update
*/
const processApiResponses = (responses: (any | DecomposedResponse)[], isResearchMode: boolean): ProcessedData => {
const processApiResponses = (responses: (any | DecomposedResponse)[],): ProcessedData => {
const result: ProcessedData = {
config,
reports: {},
documents: {},
images: {},
charts: {},
tables: {},
};
if (isResearchMode) {
const researchResponse = responses.shift();
result.reports['research_report_content'] = researchResponse;
}
if (responses.length > 0) {
const decomposedResponse = responses.shift() as DecomposedResponse;
Object.assign(result, {
@ -226,7 +214,7 @@ const UploadPage = () => {
};
/**
* Handles direct presentation generation without research or documents
* Handles direct presentation generation without documents
*/
const handleDirectPresentationGeneration = async () => {
setLoadingState({
@ -241,7 +229,7 @@ const UploadPage = () => {
n_slides: config?.slides ? parseInt(config.slides) : null,
documents: [],
images: [],
research_reports: [],
language: config?.language ?? "",
});
@ -302,8 +290,7 @@ const UploadPage = () => {
<PromptInput
value={config.prompt}
onChange={(value) => handleConfigChange("prompt", value)}
researchMode={researchMode}
setResearchMode={setResearchModel}
data-testid="prompt-input"
/>
</div>

View file

@ -3,7 +3,7 @@ import { createSlice, PayloadAction } from "@reduxjs/toolkit";
interface PresentationGenUploadState {
config: PresentationConfig | null;
reports: any;
documents: any;
images: any;
charts: any;
@ -14,7 +14,7 @@ interface PresentationGenUploadState {
const initialState: PresentationGenUploadState = {
config: null,
reports: {},
documents: {},
images: {},
charts: {},
@ -38,7 +38,6 @@ export const presentationGenUploadSlice = createSlice({
) => {
const payload = action.payload;
state.config = payload.config!;
state.reports = payload.reports;
state.documents = payload.documents;
state.images = payload.images;
state.charts = payload.charts;