Skip to content

Commit

Permalink
Merge pull request #978 from ElishaKay/nextjs-polishing
Browse files Browse the repository at this point in the history
nextjs upgrades & security patch
  • Loading branch information
assafelovic authored Nov 6, 2024
2 parents 413e5a3 + 1791581 commit 2037d97
Show file tree
Hide file tree
Showing 9 changed files with 128 additions and 49 deletions.
26 changes: 0 additions & 26 deletions backend/server/server.py
Original file line number Diff line number Diff line change
Expand Up @@ -81,26 +81,6 @@ async def read_root(request: Request):
return templates.TemplateResponse("index.html", {"request": request, "report": None})


@app.get("/getConfig")
async def get_config(
langchain_api_key: str = Header(None),
openai_api_key: str = Header(None),
tavily_api_key: str = Header(None),
google_api_key: str = Header(None),
google_cx_key: str = Header(None),
bing_api_key: str = Header(None),
searchapi_api_key: str = Header(None),
serpapi_api_key: str = Header(None),
serper_api_key: str = Header(None),
searx_url: str = Header(None)
):
return get_config_dict(
langchain_api_key, openai_api_key, tavily_api_key,
google_api_key, google_cx_key, bing_api_key,
searchapi_api_key, serpapi_api_key, serper_api_key, searx_url
)


@app.get("/files/")
async def list_files():
files = os.listdir(DOC_PATH)
Expand All @@ -113,12 +93,6 @@ async def run_multi_agents():
return await execute_multi_agents(manager)


@app.post("/setConfig")
async def set_config(config: ConfigRequest):
update_environment_variables(config.dict())
return {"message": "Config updated successfully"}


@app.post("/upload/")
async def upload_file(file: UploadFile = File(...)):
return await handle_file_upload(file, DOC_PATH)
Expand Down
52 changes: 50 additions & 2 deletions frontend/nextjs/components/Images/ImageModal.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,56 @@ import React, { useEffect } from 'react';
export default function ImageModal({ imageSrc, isOpen, onClose, onNext, onPrev }) {
if (!isOpen) return null;

// Set up keyboard event listeners
useEffect(() => {
const handleKeyDown = (e) => {
if (e.key === 'ArrowLeft') {
onPrev();
} else if (e.key === 'ArrowRight') {
onNext();
} else if (e.key === 'Escape') {
onClose();
}
};

document.addEventListener('keydown', handleKeyDown);
return () => document.removeEventListener('keydown', handleKeyDown);
}, [onClose, onNext, onPrev]);

// Swipe detection for mobile
let touchStartX = 0;
let touchEndX = 0;

const handleTouchStart = (e) => {
touchStartX = e.changedTouches[0].screenX;
};

const handleTouchEnd = (e) => {
touchEndX = e.changedTouches[0].screenX;
handleSwipeGesture();
};

const handleSwipeGesture = () => {
if (touchEndX < touchStartX - 50) {
onNext();
} else if (touchEndX > touchStartX + 50) {
onPrev();
}
};

const handleClose = (e) => {
if (e.target === e.currentTarget) {
onClose();
}
};

return (
<div className="fixed inset-0 bg-black bg-opacity-75 z-50 flex items-center justify-center p-4">
<div
className="fixed inset-0 bg-black bg-opacity-75 z-50 flex items-center justify-center p-4 overflow-auto"
onClick={handleClose}
onTouchStart={handleTouchStart}
onTouchEnd={handleTouchEnd}
>
<div className="relative max-w-[90vw] max-h-[90vh] flex items-center justify-center">
<button
onClick={onPrev}
Expand Down Expand Up @@ -32,4 +80,4 @@ export default function ImageModal({ imageSrc, isOpen, onClose, onNext, onPrev }
</div>
</div>
);
}
}
1 change: 0 additions & 1 deletion frontend/nextjs/components/ResearchBlocks/Answer.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@ export default function Answer({ answer }: { answer: string }) {
async function markdownToHtml(markdown: Compatible | undefined) {
try {
const result = await remark().use(html).process(markdown);
console.log('Markdown to HTML conversion result:', result.toString());
return result.toString();
} catch (error) {
console.error('Error converting Markdown to HTML:', error);
Expand Down
5 changes: 4 additions & 1 deletion frontend/nextjs/components/ResearchResults.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,9 @@ export const ResearchResults: React.FC<ResearchResultsProps> = ({
));

const initialReport = groupedData.find(data => data.type === 'reportBlock');
const finalReport = groupedData
.filter(data => data.type === 'reportBlock')
.pop();
const subqueriesComponent = groupedData.find(data => data.content === 'subqueries');

return (
Expand All @@ -68,7 +71,7 @@ export const ResearchResults: React.FC<ResearchResultsProps> = ({
{orderedData.length > 0 && <LogsSection logs={allLogs} />}
{sourceComponents}
{imageComponents}
{initialReport && <Answer answer={initialReport.content} />}
{finalReport && <Answer answer={finalReport.content} />}
{pathData && <AccessReport accessData={pathData.output} report={answer} />}
{chatComponents}
</>
Expand Down
3 changes: 1 addition & 2 deletions frontend/nextjs/components/Settings/Modal.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -144,8 +144,7 @@ export default function Modal({ setChatBoxSettings, chatBoxSettings }: ChatBoxPr
<div className="relative p-6 flex-auto">
<div className="tabs">
<button onClick={() => setActiveTab('search')} className={`tab-button ${activeTab === 'search' ? 'active' : ''}`}>Search Settings</button>
<button onClick={() => setActiveTab('api')} className={`tab-button ${activeTab === 'api' ? 'active' : ''}`}>API Variables</button>
</div>
</div>
{activeTab === 'search' && (
<div className="App">
<header className="App-header">
Expand Down
1 change: 0 additions & 1 deletion frontend/nextjs/components/Task/Accordion.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,6 @@ interface AccordionProps {
const plainTextFields = ['task', 'sections', 'headers', 'sources', 'research_data'];

const Accordion: React.FC<AccordionProps> = ({ logs }) => {
console.log('logs in Accordion', logs);

const getLogHeaderText = (log: Log): string => {
const regex = /📃 Source: (https?:\/\/[^\s]+)/;
Expand Down
8 changes: 7 additions & 1 deletion frontend/nextjs/hooks/useWebSocket.ts
Original file line number Diff line number Diff line change
Expand Up @@ -52,10 +52,16 @@ export const useWebSocket = (setOrderedData: React.Dispatch<React.SetStateAction
const { report_type, report_source, tone } = chatBoxSettings;
let data = "start " + JSON.stringify({ task: promptValue, report_type, report_source, tone, headers });
newSocket.send(data);

heartbeatInterval.current = window.setInterval(() => {
socket?.send('ping');
}, 3000); // Send ping every 3 seconds
};

newSocket.onclose = () => {
clearInterval(heartbeatInterval.current);
if (heartbeatInterval.current) {
clearInterval(heartbeatInterval.current);
}
setSocket(null);
};
} else if (socket) {
Expand Down
35 changes: 35 additions & 0 deletions frontend/nextjs/utils/consolidateBlocks.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
export const consolidateSourceAndImageBlocks = (groupedData: any[]) => {
// Consolidate sourceBlocks
const consolidatedSourceBlock = {
type: 'sourceBlock',
items: groupedData
.filter(item => item.type === 'sourceBlock')
.flatMap(block => block.items || [])
.filter((item, index, self) =>
index === self.findIndex(t => t.url === item.url)
)
};

// Consolidate imageBlocks
const consolidatedImageBlock = {
type: 'imagesBlock',
metadata: groupedData
.filter(item => item.type === 'imagesBlock')
.flatMap(block => block.metadata || [])
};

// Remove all existing sourceBlocks and imageBlocks
groupedData = groupedData.filter(item =>
item.type !== 'sourceBlock' && item.type !== 'imagesBlock'
);

// Add consolidated blocks if they have items
if (consolidatedSourceBlock.items.length > 0) {
groupedData.push(consolidatedSourceBlock);
}
if (consolidatedImageBlock.metadata.length > 0) {
groupedData.push(consolidatedImageBlock);
}

return groupedData;
};
46 changes: 31 additions & 15 deletions frontend/nextjs/utils/dataProcessing.ts
Original file line number Diff line number Diff line change
@@ -1,20 +1,24 @@
import { Data } from '../types/data';
import { consolidateSourceAndImageBlocks } from './consolidateBlocks';

export const preprocessOrderedData = (data: Data[]) => {
const groupedData: any[] = [];
let groupedData: any[] = [];
let currentAccordionGroup: any = null;
let currentSourceGroup: any = null;
let currentReportGroup: any = null;
let finalReportGroup: any = null;
let sourceBlockEncountered = false;
let lastSubqueriesIndex = -1;
const seenUrls = new Set<string>();
console.log('websocket data before its processed',data)

data.forEach((item: any) => {
const { type, content, metadata, output, link } = item;

if (type === 'question') {
groupedData.push({ type: 'question', content });
} else if (type === 'report') {
// Start a new report group if we don't have one
if (!currentReportGroup) {
currentReportGroup = { type: 'reportBlock', content: '' };
groupedData.push(currentReportGroup);
Expand Down Expand Up @@ -60,23 +64,24 @@ export const preprocessOrderedData = (data: Data[]) => {
} else if (content === 'added_source_url') {
if (!currentSourceGroup) {
currentSourceGroup = { type: 'sourceBlock', items: [] };
if (lastSubqueriesIndex !== -1) {
groupedData.splice(lastSubqueriesIndex + 1, 0, currentSourceGroup);
lastSubqueriesIndex = -1;
} else {
groupedData.push(currentSourceGroup);
}
sourceBlockEncountered = true;
}
let hostname = "";
try {
if (typeof metadata === 'string') {
hostname = new URL(metadata).hostname.replace('www.', '');

if (!seenUrls.has(metadata)) {
seenUrls.add(metadata);
let hostname = "";
try {
if (typeof metadata === 'string') {
hostname = new URL(metadata).hostname.replace('www.', '');
}
} catch (e) {
hostname = "unknown";
}
} catch (e) {
hostname = "unknown";
currentSourceGroup.items.push({ name: hostname, url: metadata });
}

if (currentSourceGroup.items.length > 0) {
sourceBlockEncountered = true;
}
currentSourceGroup.items.push({ name: hostname, url: metadata });
} else if (type !== 'path' && content !== '') {
if (sourceBlockEncountered) {
if (!currentAccordionGroup) {
Expand All @@ -94,10 +99,21 @@ export const preprocessOrderedData = (data: Data[]) => {
if (currentSourceGroup) {
currentSourceGroup = null;
}
if (currentReportGroup) {
// Find and remove the previous reportBlock
const reportBlockIndex = groupedData.findIndex(
item => item === currentReportGroup
);
if (reportBlockIndex !== -1) {
groupedData.splice(reportBlockIndex, 1);
}
currentReportGroup = null; // Reset the current report group
}
groupedData.push(item);
}
}
});

groupedData = consolidateSourceAndImageBlocks(groupedData);
return groupedData;
};

0 comments on commit 2037d97

Please sign in to comment.