// Array to store problem history versions const problemHistory = []; let currentHistoryIndex = -1; // Store all refined problem suggestions let storedRefinedProblems = {}; document.getElementById("tab1").style.display = "block"; function openTab(evt, tabName) { var i, tabcontent, tablinks; tabcontent = document.getElementsByClassName("tabcontent"); for (i = 0; i < tabcontent.length; i++) { tabcontent[i].style.display = "none"; } tablinks = document.getElementsByClassName("tablinks"); for (i = 0; i < tablinks.length; i++) { tablinks[i].className = tablinks[i].className.replace(" active", ""); } document.getElementById(tabName).style.display = "block"; evt.currentTarget.className += " active"; } function navigateProblemHistory(direction) { const problemInput = document.getElementById('userProblemDescription'); console.log("Current history index:", currentHistoryIndex, "Total history:", problemHistory.length); if (direction === 'prev' && currentHistoryIndex > 0) { currentHistoryIndex--; problemInput.value = problemHistory[currentHistoryIndex]; console.log("Moving to previous version:", currentHistoryIndex); } else if (direction === 'next' && currentHistoryIndex < problemHistory.length - 1) { currentHistoryIndex++; problemInput.value = problemHistory[currentHistoryIndex]; console.log("Moving to next version:", currentHistoryIndex); } updateHistoryNavigation(); } function generateQueries(event) { event.preventDefault(); const userInput = document.getElementById('userInput').value.trim(); if (!userInput) { alert('Please enter a technical problem description'); return; } // Show loading indicator document.querySelector(".progress-text").innerHTML = "Generating key issues ... Please wait." document.getElementById('globalLoadingOverlay').style.display = 'flex'; // Send message to Flask backend fetch('/generate-key-issues', { method: 'POST', body: JSON.stringify({ 'query': userInput }), headers: { 'Content-Type': 'application/json' } }) .then(response => response.json()) .then(data => { // Hide loading indicator document.getElementById('globalLoadingOverlay').style.display = 'none'; // Check if we have key issues in the response if (data.key_issues && data.key_issues.length > 0) { // Display the key issues displayKeyIssues(data.key_issues); } else if (data.error) { alert('Error: ' + data.error); } else { alert('No key issues found. Please try a different query.'); } }) .catch(error => { document.getElementById('globalLoadingOverlay').style.display = 'none'; console.error('Error:', error); alert('There was an error communicating with the server. Please try again.'); }); } function performSearch(query, queryItemElement) { if (!query.trim()) { alert('Please enter a search query'); return; } const loadingElement = queryItemElement.querySelector('.search-loading'); const tableElement = queryItemElement.querySelector('.results-table'); const tableBody = tableElement.querySelector('tbody'); // Show loading and hide previous results loadingElement.style.display = 'block'; tableElement.style.display = 'none'; // Clear previous results tableBody.innerHTML = ''; // Get checkbox values const pdfChecked = document.getElementById('pdfOption').checked; const patentChecked = document.getElementById('patentOption').checked; const webChecked = document.getElementById('webOption').checked; // Create form data with query and checkbox values const formData = new FormData(); formData.append('query', query); formData.append('pdfOption', pdfChecked); formData.append('patentOption', patentChecked); formData.append('webOption', webChecked); // Send search request to backend fetch('/search', { method: 'POST', body: formData }) .then(response => response.json()) .then(data => { // Hide loading indicator loadingElement.style.display = 'none'; if (data.results && data.results.length > 0) { // Populate table with results data.results.forEach(result => { const row = document.createElement('tr'); const typeCell = document.createElement('td'); typeCell.textContent = result.type; const titleCell = document.createElement('td'); titleCell.textContent = result.title; const bodyCell = document.createElement('td'); bodyCell.textContent = result.body; const urlCell = document.createElement('td'); const urlLink = document.createElement('a'); urlLink.href = result.url; urlLink.textContent = result.url; urlLink.className = 'url-link'; urlLink.target = '_blank'; urlCell.appendChild(urlLink); // Add "Analyze" button to the URL cell const analyzeButton = document.createElement('button'); analyzeButton.textContent = 'Analyze'; analyzeButton.className = 'action-button analyze-button'; analyzeButton.onclick = function(e) { e.preventDefault(); analyzePaper(result.url, queryItemElement); }; urlCell.appendChild(document.createElement('br')); urlCell.appendChild(analyzeButton); row.appendChild(typeCell); row.appendChild(titleCell); row.appendChild(bodyCell); row.appendChild(urlCell); tableBody.appendChild(row); }); // Show the table tableElement.style.display = 'table'; } else { // No results const row = document.createElement('tr'); const cell = document.createElement('td'); cell.colSpan = 4; // Updated to 4 since we now have 4 columns with the type column cell.textContent = 'No results found.'; cell.style.textAlign = 'center'; row.appendChild(cell); tableBody.appendChild(row); tableElement.style.display = 'table'; } }) .catch(error => { loadingElement.style.display = 'none'; console.error('Error:', error); // Show error in table const row = document.createElement('tr'); const cell = document.createElement('td'); cell.colSpan = 4; // Updated to 4 since we now have 4 columns with the type column cell.textContent = 'Error performing search. Please try again.'; cell.style.textAlign = 'center'; cell.style.color = 'red'; row.appendChild(cell); tableBody.appendChild(row); tableElement.style.display = 'table'; }); } function analyzePaper(paperUrl, queryItemElement) { const patentBackground = document.getElementById('userProblemDescription').value.trim(); if (!patentBackground) { alert('Please provide a patent background in the input field'); return; } // Find the row containing this URL const rows = queryItemElement.querySelectorAll('tbody tr'); let targetRow; let documentType = 'pdf'; // Default type for (const row of rows) { const urlLink = row.querySelector('.url-link'); if (urlLink && urlLink.href === paperUrl) { targetRow = row; // Get the document type from the first cell of the row documentType = row.cells[0].textContent.toLowerCase(); break; } } if (!targetRow) { alert('Could not find the paper in the results table'); return; } // Check if we already have analysis columns let scoreCell, justificationCell; if (targetRow.cells.length <= 4) { // We need to create the cells scoreCell = document.createElement('td'); scoreCell.className = 'score-cell'; scoreCell.innerHTML = '
'; justificationCell = document.createElement('td'); justificationCell.className = 'justification-cell'; justificationCell.innerHTML = 'Analyzing...'; targetRow.appendChild(scoreCell); targetRow.appendChild(justificationCell); } else { // Use existing cells scoreCell = targetRow.cells[4]; justificationCell = targetRow.cells[5]; scoreCell.innerHTML = '
'; justificationCell.innerHTML = 'Analyzing...'; } // Send analysis request to backend fetch('/analyze', { method: 'POST', body: JSON.stringify({ 'patent_background': patentBackground, 'pdf_url': paperUrl, 'data_type': documentType }), headers: { 'Content-Type': 'application/json' } }) .then(response => response.json()) .then(data => { if (data.error) { scoreCell.innerHTML = 'Error'; justificationCell.innerHTML = data.error; } else if (data.result) { // Get score and justification from the result const result = data.result; const score = result.score !== undefined ? result.score : 'N/A'; const justification = result.justification || 'No justification provided'; // Update cells with results scoreCell.innerHTML = score; justificationCell.innerHTML = justification; // Color-code the score if (score >= 0 && score <= 5) { const redComponent = Math.floor((score / 5) * 255); const greenComponent = Math.floor(((5 - score) / 5) * 255); scoreCell.style.backgroundColor = `rgb(${redComponent}, ${greenComponent}, 0)`; scoreCell.style.color = 'white'; scoreCell.style.fontWeight = 'bold'; scoreCell.style.textAlign = 'center'; } // Add "Extract Insights" button to the justify cell const insightsButton = document.createElement('button'); insightsButton.textContent = 'Extract Insights'; insightsButton.className = 'action-button insights-button'; insightsButton.style.marginTop = '5px'; insightsButton.style.fontSize = '0.8em'; insightsButton.onclick = function(e) { e.preventDefault(); extractInsights(paperUrl, targetRow); }; justificationCell.appendChild(document.createElement('br')); justificationCell.appendChild(insightsButton); } else { scoreCell.innerHTML = 'No data'; justificationCell.innerHTML = 'Analysis failed'; } }) .catch(error => { console.error('Error:', error); scoreCell.innerHTML = 'Error'; justificationCell.innerHTML = 'Failed to analyze paper'; }); } function extractInsights(paperUrl, row) { const patentBackground = document.getElementById('userProblemDescription').value.trim(); if (!patentBackground) { alert('Please provide a patent background in the input field'); return; } const documentType = row.cells[0].textContent.toLowerCase(); // Check if there's already an insights row for this document let insightsRow = row.nextElementSibling; if (insightsRow && insightsRow.className === 'insights-row') { // Insights row already exists, get the container insightsContainer = insightsRow.querySelector('.insights-container'); insightsContainer.innerHTML = '
Extracting insights...
'; } else { // Create insights row that spans across all columns insightsRow = document.createElement('tr'); insightsRow.className = 'insights-row'; const insightsTd = document.createElement('td'); insightsTd.colSpan = row.cells.length; insightsContainer = document.createElement('div'); insightsContainer.className = 'insights-container'; insightsContainer.innerHTML = '
Extracting insights...
'; insightsTd.appendChild(insightsContainer); insightsRow.appendChild(insightsTd); // Insert after the current row row.parentNode.insertBefore(insightsRow, row.nextSibling); } // Store the row reference as a data attribute on the container for later access insightsContainer.dataset.parentRow = row.rowIndex; // Send request to extract insights fetch('/post_insights', { method: 'POST', body: JSON.stringify({ 'patent_background': patentBackground, 'pdf_url': paperUrl, 'data_type': documentType }), headers: { 'Content-Type': 'application/json' } }) .then(response => response.json()) .then(data => { if (data.error) { insightsContainer.innerHTML = `
Error: ${data.error}
`; } else if (data.result && data.result.insights) { // Create header with title and actions const insightsHeader = document.createElement('div'); insightsHeader.className = 'insights-header'; const insightsTitle = document.createElement('div'); insightsTitle.className = 'insights-title'; insightsTitle.textContent = 'Document Insights'; const insightsActions = document.createElement('div'); insightsActions.className = 'insights-actions'; // Store the insights for this specific container const containerInsights = [...data.result.insights]; insightsContainer.dataset.allInsights = JSON.stringify(containerInsights); const selectAllBtn = document.createElement('button'); selectAllBtn.className = 'insights-button select-all-btn'; selectAllBtn.textContent = 'Select All'; // Use a closure to ensure the button has access to the correct container and row selectAllBtn.addEventListener('click', function() { const container = this.closest('.insights-container'); const parentRow = row; const allInsights = JSON.parse(container.dataset.allInsights || '[]'); const tags = container.querySelectorAll('.insight-tag'); tags.forEach(tag => tag.classList.add('selected')); parentRow.dataset.selectedInsights = JSON.stringify(allInsights); parentRow.dataset.unselectedInsights = JSON.stringify([]); // Trigger check for enabling/disabling enhance button checkSelectedInsights(); }); const clearAllBtn = document.createElement('button'); clearAllBtn.className = 'insights-button clear-all-btn'; clearAllBtn.textContent = 'Clear All'; // Use a closure to ensure the button has access to the correct container and row clearAllBtn.addEventListener('click', function() { const container = this.closest('.insights-container'); const parentRow = row; const allInsights = JSON.parse(container.dataset.allInsights || '[]'); const tags = container.querySelectorAll('.insight-tag'); tags.forEach(tag => tag.classList.remove('selected')); parentRow.dataset.selectedInsights = JSON.stringify([]); parentRow.dataset.unselectedInsights = JSON.stringify(allInsights); // Trigger check for enabling/disabling enhance button checkSelectedInsights(); }); insightsActions.appendChild(selectAllBtn); insightsActions.appendChild(clearAllBtn); insightsHeader.appendChild(insightsTitle); insightsHeader.appendChild(insightsActions); // Create insight tags const insightsList = document.createElement('div'); insightsList.className = 'insights-list'; // Clear the container and add the new elements insightsContainer.innerHTML = ''; insightsContainer.appendChild(insightsHeader); insightsContainer.appendChild(insightsList); // Initialize selected insights const selectedInsights = []; const unselectedInsights = []; // Add insight tags data.result.insights.forEach(insight => { const tagElement = document.createElement('div'); tagElement.className = 'insight-tag'; tagElement.textContent = insight; tagElement.addEventListener('click', function() { this.classList.toggle('selected'); // Update selected insights updateSelectedInsights(row, insightsContainer); // Trigger check for enabling/disabling enhance button checkSelectedInsights(); }); // Add to unselected by default // tagElement.classList.add('selected'); unselectedInsights.push(insight); insightsList.appendChild(tagElement); }); // Store initial selections row.dataset.selectedInsights = JSON.stringify(selectedInsights); row.dataset.unselectedInsights = JSON.stringify(unselectedInsights); // Trigger check for enabling/disabling enhance button immediately checkSelectedInsights(); } else { insightsContainer.innerHTML = '
No insights found
'; } }) .catch(error => { console.error('Error:', error); insightsContainer.innerHTML = `
Error extracting insights: ${error.message}
`; }); } function updateSelectedInsights(row, insightsContainer) { const selectedInsights = []; const unselectedInsights = []; const tags = insightsContainer.querySelectorAll('.insight-tag'); tags.forEach(tag => { if (tag.classList.contains('selected')) { selectedInsights.push(tag.textContent); } else { unselectedInsights.push(tag.textContent); } }); row.dataset.selectedInsights = JSON.stringify(selectedInsights); row.dataset.unselectedInsights = JSON.stringify(unselectedInsights); } function checkSelectedInsights() { const selectedInsights = collectAllSelectedInsights(); const enhanceButton = document.getElementById('enhanceProblemButton'); if (selectedInsights.length > 0) { enhanceButton.classList.remove('disabled'); enhanceButton.disabled = false; } else { enhanceButton.classList.add('disabled'); enhanceButton.disabled = true; } } function collectAllSelectedInsights() { const allSelectedInsights = []; const queryItems = document.querySelectorAll('.query-item'); queryItems.forEach(queryItem => { const rows = queryItem.querySelectorAll('tbody tr:not(.insights-row)'); rows.forEach(row => { if (row.dataset.selectedInsights) { try { const selectedInsights = JSON.parse(row.dataset.selectedInsights); selectedInsights.forEach(insight => { if (!allSelectedInsights.includes(insight)) { allSelectedInsights.push(insight); } }); } catch (e) { console.error('Error parsing selected insights:', e); } } }); }); return allSelectedInsights; } function exportToExcel() { // Show loading overlay const loadingOverlay = document.getElementById('globalLoadingOverlay'); if (loadingOverlay) { loadingOverlay.style.display = 'flex'; loadingOverlay.querySelector('.progress-text').textContent = 'Generating Excel file...'; } try { // Collect all data from all tables const allData = []; const queryItems = document.querySelectorAll('.query-item'); queryItems.forEach(queryItem => { // Get the search query text for this table const queryText = queryItem.querySelector('.query-field').value; // Get all rows in this table const rows = queryItem.querySelectorAll('tbody tr:not(.insights-row)'); rows.forEach(row => { // Skip empty rows or error rows if (row.cells.length === 1 && row.cells[0].colSpan > 1) { return; // Skip "No results found" rows } // Prepare object for this row const rowData = { 'Topic': queryText, 'Type': row.cells[0].textContent, 'Title': row.cells[1].textContent, 'Description': row.cells[2].textContent, 'URL': row.querySelector('.url-link')?.href || '' }; // Add score and justification if they exist if (row.cells.length > 4) { rowData['Score'] = row.cells[4].textContent; rowData['Justification'] = row.cells[5].textContent.split('\n')[0]; // Only get the justification text } else { rowData['Score'] = ''; rowData['Justification'] = ''; } // Add selected and unselected insights if they exist if (row.dataset.selectedInsights) { try { const selectedInsights = JSON.parse(row.dataset.selectedInsights); rowData['Selected Insights'] = selectedInsights.join('; '); } catch (e) { rowData['Selected Insights'] = ''; } } else { rowData['Selected Insights'] = ''; } if (row.dataset.unselectedInsights) { try { const unselectedInsights = JSON.parse(row.dataset.unselectedInsights); rowData['Unselected Insights'] = unselectedInsights.join('; '); } catch (e) { rowData['Unselected Insights'] = ''; } } else { rowData['Unselected Insights'] = ''; } allData.push(rowData); }); }); // Check if we have any data if (allData.length === 0) { if (loadingOverlay) loadingOverlay.style.display = 'none'; alert('No data to export. Please perform a search first.'); return; } // Get all problem versions const problemVersions = {}; if (problemHistory.length > 0) { problemHistory.forEach((problem, index) => { problemVersions[`Problem Version ${index + 1}`] = problem; }); } else { // If no history, just use the current problem const currentProblem = document.getElementById('userProblemDescription').value.trim(); if (currentProblem) { problemVersions['Problem Version 1'] = currentProblem; } } // Send to server for Excel generation fetch('/export-excel', { method: 'POST', body: JSON.stringify({ 'tableData': allData, 'userQuery': document.getElementById('userProblemDescription').value, 'problemVersions': problemVersions }), headers: { 'Content-Type': 'application/json' } }) .then(response => { if (!response.ok) { throw new Error(`Server error: ${response.status}`); } return response.blob(); }) .then(blob => { // Hide loading overlay if (loadingOverlay) loadingOverlay.style.display = 'none'; // Create URL for the blob const url = window.URL.createObjectURL(new Blob([blob], { type: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet' })); // Create a link and trigger download const a = document.createElement('a'); a.href = url; a.download = 'patent_search_results.xlsx'; document.body.appendChild(a); a.click(); // Clean up window.URL.revokeObjectURL(url); document.body.removeChild(a); }) .catch(error => { console.error('Error exporting to Excel:', error); if (loadingOverlay) loadingOverlay.style.display = 'none'; alert(`Error exporting to Excel: ${error.message}`); }); } catch (error) { console.error('Error preparing Excel data:', error); if (loadingOverlay) loadingOverlay.style.display = 'none'; alert(`Error preparing data for export: ${error.message}`); } } function hasSearchResults() { const resultsContainer = document.getElementById('resultsContainer'); const hasResults = resultsContainer && resultsContainer.style.display !== 'none'; const hasTables = document.querySelectorAll('.results-table[style*="display: table"]').length > 0; return hasResults && hasTables; } function analyzeAllPapers() { // Show loading overlay const loadingOverlay = document.getElementById('globalLoadingOverlay'); if (loadingOverlay) loadingOverlay.style.display = 'flex'; if (loadingOverlay) loadingOverlay.querySelector('.progress-text').textContent = 'Analyzing all papers...'; // Get all query items const queryItems = document.querySelectorAll('.query-item'); let totalToAnalyze = 0; let completedAnalyses = 0; // Count total papers that need analysis queryItems.forEach(queryItem => { const rows = queryItem.querySelectorAll('tbody tr'); rows.forEach(row => { if (row.cells.length <= 4 || row.cells[4].textContent.trim() === 'Error' || row.cells[4].textContent.trim() === 'N/A' || row.cells[4].textContent.trim() === '') { totalToAnalyze++; } }); }); if (totalToAnalyze === 0) { alert('No papers need analysis'); if (loadingOverlay) loadingOverlay.style.display = 'none'; return; } // Function to update progress function updateProgress() { completedAnalyses++; if (loadingOverlay) { const progressElement = loadingOverlay.querySelector('.progress-text'); if (progressElement) { progressElement.textContent = `Analyzing papers: ${completedAnalyses}/${totalToAnalyze}`; } } if (completedAnalyses >= totalToAnalyze) { if (loadingOverlay) loadingOverlay.style.display = 'none'; } } // Analyze each paper that needs it queryItems.forEach(queryItem => { const rows = queryItem.querySelectorAll('tbody tr'); rows.forEach(row => { // Check if this row needs analysis if (row.cells.length <= 4 || row.cells[4].textContent.trim() === 'Error' || row.cells[4].textContent.trim() === 'N/A' || row.cells[4].textContent.trim() === '') { // Get the URL const urlLink = row.querySelector('.url-link'); const documentType = row.cells[0].textContent.toLowerCase(); if (urlLink && urlLink.href) { // Create a promise for this analysis const promise = new Promise((resolve) => { // Prepare for analysis const patentBackground = document.getElementById('userProblemDescription').value.trim(); // Create score and justification cells if needed let scoreCell, justificationCell; if (row.cells.length <= 4) { scoreCell = document.createElement('td'); scoreCell.className = 'score-cell'; scoreCell.innerHTML = '
'; justificationCell = document.createElement('td'); justificationCell.className = 'justification-cell'; justificationCell.innerHTML = 'Analyzing...'; row.appendChild(scoreCell); row.appendChild(justificationCell); } else { scoreCell = row.cells[4]; justificationCell = row.cells[5]; scoreCell.innerHTML = '
'; justificationCell.innerHTML = 'Analyzing...'; } // Send analysis request fetch('/analyze', { method: 'POST', body: JSON.stringify({ 'patent_background': patentBackground, 'pdf_url': urlLink.href, 'data_type': documentType }), headers: { 'Content-Type': 'application/json' } }) .then(response => response.json()) .then(data => { if (data.error) { scoreCell.innerHTML = 'Error'; justificationCell.innerHTML = data.error; } else if (data.result) { // Get score and justification const result = data.result; const score = result.score !== undefined ? result.score : 'N/A'; const justification = result.justification || 'No justification provided'; // Update cells scoreCell.innerHTML = score; justificationCell.innerHTML = justification; // Color-code score if (score >= 0 && score <= 5) { const redComponent = Math.floor((score / 5) * 255); const greenComponent = Math.floor(((5 - score) / 5) * 255); scoreCell.style.backgroundColor = `rgb(${redComponent}, ${greenComponent}, 0)`; scoreCell.style.color = 'white'; scoreCell.style.fontWeight = 'bold'; scoreCell.style.textAlign = 'center'; } // Add "Extract Insights" button to the justify cell - for Analyze All function const insightsButton = document.createElement('button'); insightsButton.textContent = 'Extract Insights'; insightsButton.className = 'action-button insights-button'; insightsButton.style.marginTop = '5px'; insightsButton.style.fontSize = '0.8em'; insightsButton.onclick = function(e) { e.preventDefault(); extractInsights(urlLink.href, row); }; justificationCell.appendChild(document.createElement('br')); justificationCell.appendChild(insightsButton); } else { scoreCell.innerHTML = 'No data'; justificationCell.innerHTML = 'Analysis failed'; } resolve(); }) .catch(error => { console.error('Error:', error); scoreCell.innerHTML = 'Error'; justificationCell.innerHTML = 'Failed to analyze paper'; resolve(); }); }); // When this analysis is done, update the progress promise.then(() => { updateProgress(); }); } else { // No URL found, count as completed updateProgress(); } } }); }); } function removeFailedAnalyses() { const queryItems = document.querySelectorAll('.query-item'); let removedCount = 0; queryItems.forEach(queryItem => { const tbody = queryItem.querySelector('tbody'); const rows = Array.from(tbody.querySelectorAll('tr')); rows.forEach(row => { if (row.cells.length > 4) { const scoreText = row.cells[4].textContent.trim(); if (scoreText === 'Error' || scoreText === 'N/A' || scoreText === 'No data') { tbody.removeChild(row); removedCount++; } } }); }); // Create and display a simple notification instead of alert const notification = document.createElement('div'); notification.className = 'simple-notification'; notification.textContent = `Removed ${removedCount} papers with failed analyses`; notification.style.position = 'fixed'; notification.style.top = '20px'; notification.style.right = '20px'; notification.style.background = '#4CAF50'; notification.style.color = 'white'; notification.style.padding = '15px'; notification.style.borderRadius = '5px'; notification.style.boxShadow = '0 2px 5px rgba(0,0,0,0.2)'; notification.style.zIndex = '10000'; // Add notification to the body document.body.appendChild(notification); // Remove notification after 3 seconds setTimeout(() => { if (notification.parentNode) { notification.parentNode.removeChild(notification); } }, 3000); } function extractAllInsights() { const patentBackground = document.getElementById('userProblemDescription').value.trim(); if (!patentBackground) { alert('Please provide a patent background in the input field'); return; } // Show loading overlay const loadingOverlay = document.getElementById('globalLoadingOverlay'); if (loadingOverlay) { loadingOverlay.style.display = 'flex'; loadingOverlay.querySelector('.progress-text').textContent = 'Extracting insights from all documents...'; } // Get all query items const queryItems = document.querySelectorAll('.query-item'); let totalDocuments = 0; let completedDocuments = 0; // Count total analyzed documents that need insights extraction const analyzedRows = []; queryItems.forEach(queryItem => { const rows = queryItem.querySelectorAll('tbody tr:not(.insights-row)'); rows.forEach(row => { // Only include rows that have been analyzed (have score and justification cells) if (row.cells.length > 4 && row.cells[4].textContent.trim() !== 'Error' && row.cells[4].textContent.trim() !== 'N/A' && row.cells[4].textContent.trim() !== '') { analyzedRows.push(row); totalDocuments++; } }); }); if (totalDocuments === 0) { if (loadingOverlay) loadingOverlay.style.display = 'none'; alert('No analyzed documents found. Please analyze documents first.'); return; } // Function to update progress function updateProgress() { completedDocuments++; if (loadingOverlay) { const progressElement = loadingOverlay.querySelector('.progress-text'); if (progressElement) { progressElement.textContent = `Extracting insights: ${completedDocuments}/${totalDocuments}`; } } if (completedDocuments >= totalDocuments) { if (loadingOverlay) loadingOverlay.style.display = 'none'; checkSelectedInsights(); // Update enhance button state based on selected insights } } // Process each analyzed document sequentially to avoid overwhelming the server function processNextDocument(index) { if (index >= analyzedRows.length) { return; // All documents processed } const row = analyzedRows[index]; const urlLink = row.querySelector('.url-link'); const documentType = row.cells[0].textContent.toLowerCase(); if (!urlLink || !urlLink.href) { updateProgress(); processNextDocument(index + 1); return; } // Check if there's already an insights row for this document let insightsRow = row.nextElementSibling; if (insightsRow && insightsRow.className === 'insights-row') { // Insights row already exists, get the container insightsContainer = insightsRow.querySelector('.insights-container'); insightsContainer.innerHTML = '
Extracting insights...
'; } else { // Create insights row that spans across all columns insightsRow = document.createElement('tr'); insightsRow.className = 'insights-row'; const insightsTd = document.createElement('td'); insightsTd.colSpan = row.cells.length; insightsContainer = document.createElement('div'); insightsContainer.className = 'insights-container'; insightsContainer.innerHTML = '
Extracting insights...
'; insightsTd.appendChild(insightsContainer); insightsRow.appendChild(insightsTd); // Insert after the current row row.parentNode.insertBefore(insightsRow, row.nextSibling); } // Store the row reference as a data attribute on the container for later access insightsContainer.dataset.parentRow = row.rowIndex; // Send request to extract insights fetch('/post_insights', { method: 'POST', body: JSON.stringify({ 'patent_background': patentBackground, 'pdf_url': urlLink.href, 'data_type': documentType }), headers: { 'Content-Type': 'application/json' } }) .then(response => response.json()) .then(data => { if (data.error) { insightsContainer.innerHTML = `
Error: ${data.error}
`; } else if (data.result && data.result.insights) { // Create header with title and actions const insightsHeader = document.createElement('div'); insightsHeader.className = 'insights-header'; const insightsTitle = document.createElement('div'); insightsTitle.className = 'insights-title'; insightsTitle.textContent = 'Document Insights'; const insightsActions = document.createElement('div'); insightsActions.className = 'insights-actions'; // Store the insights for this specific container const containerInsights = [...data.result.insights]; insightsContainer.dataset.allInsights = JSON.stringify(containerInsights); const selectAllBtn = document.createElement('button'); selectAllBtn.className = 'insights-button select-all-btn'; selectAllBtn.textContent = 'Select All'; selectAllBtn.addEventListener('click', function() { const container = this.closest('.insights-container'); const parentRow = row; const allInsights = JSON.parse(container.dataset.allInsights || '[]'); const tags = container.querySelectorAll('.insight-tag'); tags.forEach(tag => tag.classList.add('selected')); parentRow.dataset.selectedInsights = JSON.stringify(allInsights); parentRow.dataset.unselectedInsights = JSON.stringify([]); checkSelectedInsights(); }); const clearAllBtn = document.createElement('button'); clearAllBtn.className = 'insights-button clear-all-btn'; clearAllBtn.textContent = 'Clear All'; clearAllBtn.addEventListener('click', function() { const container = this.closest('.insights-container'); const parentRow = row; const allInsights = JSON.parse(container.dataset.allInsights || '[]'); const tags = container.querySelectorAll('.insight-tag'); tags.forEach(tag => tag.classList.remove('selected')); parentRow.dataset.selectedInsights = JSON.stringify([]); parentRow.dataset.unselectedInsights = JSON.stringify(allInsights); checkSelectedInsights(); }); insightsActions.appendChild(selectAllBtn); insightsActions.appendChild(clearAllBtn); insightsHeader.appendChild(insightsTitle); insightsHeader.appendChild(insightsActions); // Create insight tags const insightsList = document.createElement('div'); insightsList.className = 'insights-list'; // Clear the container and add the new elements insightsContainer.innerHTML = ''; insightsContainer.appendChild(insightsHeader); insightsContainer.appendChild(insightsList); // Initialize selected insights const selectedInsights = []; const unselectedInsights = []; // Add insight tags data.result.insights.forEach(insight => { const tagElement = document.createElement('div'); tagElement.className = 'insight-tag'; tagElement.textContent = insight; tagElement.addEventListener('click', function() { this.classList.toggle('selected'); updateSelectedInsights(row, insightsContainer); checkSelectedInsights(); }); // Add to unselected by default // tagElement.classList.add('selected'); unselectedInsights.push(insight); insightsList.appendChild(tagElement); }); // Store initial selections row.dataset.selectedInsights = JSON.stringify(selectedInsights); row.dataset.unselectedInsights = JSON.stringify(unselectedInsights); } else { insightsContainer.innerHTML = '
No insights found
'; } // Process next document updateProgress(); processNextDocument(index + 1); }) .catch(error => { console.error('Error:', error); insightsContainer.innerHTML = `
Error extracting insights: ${error.message}
`; // Continue with next document even if this one failed updateProgress(); processNextDocument(index + 1); }); } // Start processing documents processNextDocument(0); } function groupInsightsByScore() { // Get all query items const queryItems = document.querySelectorAll('.query-item'); let hasInsights = false; // Create structure to hold insights grouped by score const insightsByScore = { 5: { insights: [], sources: [] }, 4: { insights: [], sources: [] }, 3: { insights: [], sources: [] }, 2: { insights: [], sources: [] }, 1: { insights: [], sources: [] }, 0: { insights: [], sources: [] } }; // Collect all insights from all documents and group by score queryItems.forEach(queryItem => { const rows = queryItem.querySelectorAll('tbody tr:not(.insights-row)'); rows.forEach(row => { // Skip if no score or insights if (row.cells.length <= 4 || !row.dataset.selectedInsights) { return; } // Get the score const scoreText = row.cells[4].textContent.trim(); if (scoreText === 'Error' || scoreText === 'N/A' || isNaN(parseFloat(scoreText))) { return; } const score = Math.round(parseFloat(scoreText)); const urlLink = row.querySelector('.url-link'); if (!urlLink) return; // Get insights from this document try { const selectedInsights = JSON.parse(row.dataset.selectedInsights || '[]'); const unselectedInsights = JSON.parse(row.dataset.unselectedInsights || '[]'); const allInsights = [...selectedInsights, ...unselectedInsights]; // Add insights to the appropriate score group if (score >= 0 && score <= 5 && allInsights.length > 0) { hasInsights = true; // For all insights in this document allInsights.forEach(insight => { // Check if this insight is already in the group const existingIndex = insightsByScore[score].insights.findIndex(i => i === insight); if (existingIndex === -1) { // New insight insightsByScore[score].insights.push(insight); insightsByScore[score].sources.push({ url: urlLink.href, title: row.cells[1].textContent.trim().substring(0, 30) + '...', selected: selectedInsights.includes(insight) }); } }); } } catch (e) { console.error('Error parsing insights:', e); } }); }); if (!hasInsights) { alert('No insights found. Please analyze documents and extract insights first.'); return; } // Create or get the grouped insights container let container = document.getElementById('groupedInsightsContainer'); if (!container) { container = document.createElement('div'); container.id = 'groupedInsightsContainer'; container.className = 'grouped-insights-container'; // Insert after the problem input card const card = document.querySelector("#tab2 .card"); card.parentNode.insertBefore(container, card.nextSibling); } // Create header const header = document.createElement('div'); header.className = 'grouped-insights-header'; header.innerHTML = `
Insights Grouped by Score
×
`; // Create content area const content = document.createElement('div'); content.className = 'grouped-insights-content'; // Create score groups for (let score = 5; score >= 0; score--) { const insights = insightsByScore[score].insights; const sources = insightsByScore[score].sources; if (insights.length === 0) continue; const scoreGroup = document.createElement('div'); scoreGroup.className = 'score-group'; scoreGroup.dataset.score = score; // Create score header const scoreHeader = document.createElement('div'); scoreHeader.className = 'score-group-header'; let scoreColor = ''; if (score >= 0 && score <= 5) { const redComponent = Math.floor((score / 5) * 255); const greenComponent = Math.floor(((5 - score) / 5) * 255); scoreColor = `background-color: rgb(${redComponent}, ${greenComponent}, 0); color: white;`; } scoreHeader.innerHTML = `
${score} Score ${score} Insights (${insights.length})
`; // Create insights list const insightsList = document.createElement('div'); insightsList.className = 'score-insights-list'; // Add each insight insights.forEach((insight, index) => { const source = sources[index]; const tagElement = document.createElement('div'); tagElement.className = `grouped-insight-tag${source.selected ? ' selected' : ''}`; tagElement.dataset.score = score; tagElement.dataset.index = index; tagElement.dataset.source = source.url; // Create insight text with source link tagElement.innerHTML = ` ${insight} ${score} `; // Add click event to toggle selection tagElement.addEventListener('click', function(e) { // Prevent clicking on the source link from toggling selection if (e.target.classList.contains('insight-source')) return; this.classList.toggle('selected'); updateGroupedInsightSelections(); }); insightsList.appendChild(tagElement); }); // Add header and list to score group scoreGroup.appendChild(scoreHeader); scoreGroup.appendChild(insightsList); // Add score group to content content.appendChild(scoreGroup); } // Clear the container and add new content container.innerHTML = ''; container.appendChild(header); container.appendChild(content); // Show the container container.style.display = 'block'; // Collapse all accordions const accordions = document.querySelectorAll('.accordion-section'); accordions.forEach(accordion => { const header = accordion.querySelector('.accordion-header'); const body = accordion.querySelector('.accordion-body'); if (header && body && !header.classList.contains('collapsed')) { header.classList.add('collapsed'); body.classList.add('collapsed'); // Update the toggle icon const toggleIcon = header.querySelector('.toggle-icon'); if (toggleIcon) toggleIcon.textContent = '▶'; } }); // Scroll to the insights container container.scrollIntoView({ behavior: 'smooth' }); // Remove the pulse animation after a few seconds setTimeout(() => { const aiSelectBtn = document.getElementById('aiSelectButton'); if (aiSelectBtn) { aiSelectBtn.classList.remove('pulse'); } }, 5000); } function enhanceProblem() { const problemInput = document.getElementById('userProblemDescription'); const originalProblem = problemInput.value.trim(); if (!originalProblem) { alert('Please provide a technical problem description first'); return; } const selectedInsights = collectAllSelectedInsights(); if (selectedInsights.length === 0) { alert('Please select at least one insight to enhance the problem'); return; } // Get user comments if any const userComments = document.getElementById('insightCommentArea')?.value || ''; // If we have stored refined problems for this exact problem, just show them const currentProblemKey = JSON.stringify({ problem: originalProblem, insights: selectedInsights.sort(), comments: userComments }); if (storedRefinedProblems[currentProblemKey]) { showRefinedProblems(storedRefinedProblems[currentProblemKey]); return; } // Show loading overlay const loadingOverlay = document.getElementById('globalLoadingOverlay'); if (loadingOverlay) { loadingOverlay.style.display = 'flex'; loadingOverlay.querySelector('.progress-text').textContent = 'Enhancing problem statement...'; } // Send request to backend to refine the problem fetch('/refine-problem', { method: 'POST', body: JSON.stringify({ 'original_problem': originalProblem, 'insights': selectedInsights, 'user_comments': userComments }), headers: { 'Content-Type': 'application/json' } }) .then(response => response.json()) .then(data => { // Hide loading overlay if (loadingOverlay) loadingOverlay.style.display = 'none'; if (data.error) { alert(`Error: ${data.error}`); return; } if (data.result) { // Add current problem to history if not already there if (currentHistoryIndex === -1) { problemHistory.push(originalProblem); currentHistoryIndex = 0; } // Store the refined problems for future use storedRefinedProblems[currentProblemKey] = data.result; // Show refined problem options showRefinedProblems(data.result); } }) .catch(error => { console.error('Error:', error); if (loadingOverlay) loadingOverlay.style.display = 'none'; alert(`Error enhancing problem: ${error.message}`); }); } function closeGroupedInsights() { const container = document.getElementById('groupedInsightsContainer'); if (container) { container.style.display = 'none'; } } // Select all insights for a specific score function selectAllInScore(score) { const container = document.getElementById('groupedInsightsContainer'); const tags = container.querySelectorAll(`.grouped-insight-tag[data-score="${score}"]`); tags.forEach(tag => { tag.classList.add('selected'); }); updateGroupedInsightSelections(); } // Clear all insights for a specific score function clearAllInScore(score) { const container = document.getElementById('groupedInsightsContainer'); const tags = container.querySelectorAll(`.grouped-insight-tag[data-score="${score}"]`); tags.forEach(tag => { tag.classList.remove('selected'); }); updateGroupedInsightSelections(); } function updateGroupedInsightSelections() { // Get all selected insights from the grouped view const container = document.getElementById('groupedInsightsContainer'); const selectedTags = container.querySelectorAll('.grouped-insight-tag.selected'); // Create a mapping of URL to selected insights const selectionsBySource = {}; // Process each selected tag selectedTags.forEach(tag => { const insight = tag.textContent.trim().replace(/\d+$/, '').trim(); // Remove the score number at the end const sourceUrl = tag.dataset.source; if (!selectionsBySource[sourceUrl]) { selectionsBySource[sourceUrl] = []; } selectionsBySource[sourceUrl].push(insight); }); // Now update the original document rows const queryItems = document.querySelectorAll('.query-item'); queryItems.forEach(queryItem => { const rows = queryItem.querySelectorAll('tbody tr:not(.insights-row)'); rows.forEach(row => { const urlLink = row.querySelector('.url-link'); if (!urlLink) return; const sourceUrl = urlLink.href; // If we have selections for this source if (selectionsBySource[sourceUrl]) { // Get all insights for this row try { // Combine selected and unselected to get all insights const currentSelected = JSON.parse(row.dataset.selectedInsights || '[]'); const currentUnselected = JSON.parse(row.dataset.unselectedInsights || '[]'); const allInsights = [...currentSelected, ...currentUnselected]; // New selected and unselected based on grouped view const newSelected = []; const newUnselected = []; // Process each insight allInsights.forEach(insight => { if (selectionsBySource[sourceUrl].includes(insight)) { newSelected.push(insight); } else { newUnselected.push(insight); } }); // Update the dataset row.dataset.selectedInsights = JSON.stringify(newSelected); row.dataset.unselectedInsights = JSON.stringify(newUnselected); } catch (e) { console.error('Error updating insights selections:', e); } } }); }); // Update enhance button state checkSelectedInsights(); } function showRefinedProblems(result) { const refinedContainer = document.getElementById('refinedProblemContainer'); const tabs = document.getElementById('refinedProblemTabs'); const content = document.getElementById('refinedProblemContent'); // Clear previous content tabs.innerHTML = ''; content.innerHTML = ''; // Add tabs and content for each refined problem let isFirst = true; for (const key in result) { if (result.hasOwnProperty(key)) { const problem = result[key]; // Create tab const tab = document.createElement('div'); tab.className = `refined-problem-tab ${isFirst ? 'active' : ''}`; tab.dataset.target = key; tab.textContent = `Option ${key.split('_')[1]}`; tab.onclick = function() { document.querySelectorAll('.refined-problem-tab').forEach(t => t.classList.remove('active')); document.querySelectorAll('.refined-problem').forEach(p => p.classList.remove('active')); tab.classList.add('active'); document.getElementById(key).classList.add('active'); }; tabs.appendChild(tab); // Create content const problemDiv = document.createElement('div'); problemDiv.className = `refined-problem ${isFirst ? 'active' : ''}`; problemDiv.id = key; const title = document.createElement('div'); title.className = 'refined-problem-title'; title.textContent = problem.title; const description = document.createElement('div'); description.className = 'refined-problem-description'; description.textContent = problem.description; const applyButton = document.createElement('button'); applyButton.className = 'apply-problem-btn'; applyButton.textContent = 'Apply This Problem'; applyButton.onclick = function() { applyRefinedProblem(problem.description); }; problemDiv.appendChild(title); problemDiv.appendChild(description); problemDiv.appendChild(applyButton); content.appendChild(problemDiv); isFirst = false; } } // Show the container refinedContainer.style.display = 'block'; // Scroll to the container refinedContainer.scrollIntoView({ behavior: 'smooth' }); } function applyRefinedProblem(problemText) { const problemInput = document.getElementById('userProblemDescription'); // Add current problem to history problemHistory.push(problemInput.value); currentHistoryIndex = problemHistory.length - 1; // Set to latest version // Update problem text with the new version problemInput.value = problemText; // Now add the new version to history problemHistory.push(problemText); currentHistoryIndex = problemHistory.length - 1; // Update index to point to the newly added version // Update history navigation display updateHistoryNavigation(); // Display is kept visible, removed: document.getElementById('refinedProblemContainer').style.display = 'none'; // Focus on the problem input problemInput.focus(); console.log("Problem history after applying:", problemHistory, "Current index:", currentHistoryIndex); } function updateHistoryNavigation() { const historyNav = document.getElementById('problemHistoryNav'); const prevBtn = historyNav.querySelector('.history-prev'); const nextBtn = historyNav.querySelector('.history-next'); const status = historyNav.querySelector('.history-status'); // Update buttons state prevBtn.classList.toggle('disabled', currentHistoryIndex <= 0); nextBtn.classList.toggle('disabled', currentHistoryIndex >= problemHistory.length - 1); // Update status text if (problemHistory.length > 0) { status.textContent = `Version ${currentHistoryIndex + 1} of ${problemHistory.length}`; historyNav.style.display = 'flex'; } else { historyNav.style.display = 'none'; } } function aiSelectInsights() { const patentBackground = document.getElementById('userProblemDescription').value.trim(); if (!patentBackground) { alert('Please provide a patent background in the input field'); return; } // Change button appearance to show it's working const aiSelectBtn = document.getElementById('aiSelectButton'); if (aiSelectBtn) { aiSelectBtn.disabled = true; aiSelectBtn.textContent = 'AI Selecting...'; aiSelectBtn.style.opacity = '0.7'; } // Show loading overlay const loadingOverlay = document.getElementById('globalLoadingOverlay'); if (loadingOverlay) { loadingOverlay.style.display = 'flex'; loadingOverlay.querySelector('.progress-text').textContent = 'AI selecting the most relevant insights...'; } // Get all insights from all score groups const container = document.getElementById('groupedInsightsContainer'); const insightTags = container.querySelectorAll('.grouped-insight-tag'); const insights = Array.from(insightTags).map(tag => { return tag.textContent.trim().replace(/\d+$/, '').trim(); // Remove the score number }); if (insights.length === 0) { if (loadingOverlay) loadingOverlay.style.display = 'none'; alert('No insights found'); return; } // Send request to backend to get AI selection fetch('/ai-select-insights', { method: 'POST', body: JSON.stringify({ 'patent_background': patentBackground, 'insights': insights }), headers: { 'Content-Type': 'application/json' } }) .then(response => response.json()) .then(data => { // Reset button appearance if (aiSelectBtn) { aiSelectBtn.disabled = false; aiSelectBtn.textContent = 'AI Select Insights'; aiSelectBtn.style.opacity = '1'; } if (loadingOverlay) loadingOverlay.style.display = 'none'; if (data.error) { alert(`Error: ${data.error}`); return; } if (data.selected_insights && data.selected_insights.length > 0) { // First clear all selections insightTags.forEach(tag => { tag.classList.remove('selected'); }); // Then select the recommended insights insightTags.forEach(tag => { const insightText = tag.textContent.trim().replace(/\d+$/, '').trim(); if (data.selected_insights.includes(insightText)) { tag.classList.add('selected'); } }); // Update the original document rows updateGroupedInsightSelections(); // Remove alert notification - user can see the selected insights visually // alert(`AI selected ${data.selected_insights.length} insights from ${insights.length} available insights`); } else { alert('AI could not identify any relevant insights to select'); } }) .catch(error => { console.error('Error:', error); // Reset button appearance if (aiSelectBtn) { aiSelectBtn.disabled = false; aiSelectBtn.textContent = 'AI Select Insights'; aiSelectBtn.style.opacity = '1'; } if (loadingOverlay) loadingOverlay.style.display = 'none'; alert(`Error using AI to select insights: ${error.message}`); }); } function generateSearchQueries() { function addQueryField(queryText = '', container = null) { const queriesContainer = container || document.getElementById('queriesContainer'); // Count existing query items in this container for indexing const queryItems = container ? container.querySelectorAll('.query-item') : document.getElementById('queriesContainer').querySelectorAll('.query-item'); const queryIndex = queryItems.length + 1; // Create main container for this query item const queryItem = document.createElement('div'); queryItem.className = 'query-item'; // Create container for query field and buttons const queryContainer = document.createElement('div'); queryContainer.className = 'query-container'; // Input field const queryField = document.createElement('input'); queryField.type = 'text'; queryField.className = 'query-field'; queryField.value = queryText; queryField.placeholder = `Search Query ${queryIndex}`; // Delete button const deleteButton = document.createElement('button'); deleteButton.type = 'button'; deleteButton.className = 'action-button delete-button'; deleteButton.textContent = 'Delete'; deleteButton.onclick = function() { queryItem.parentNode.removeChild(queryItem); // Update the placeholder numbers for remaining queries within this container const parent = container || document.getElementById('queriesContainer'); const items = parent.querySelectorAll('.query-item'); items.forEach((item, idx) => { const field = item.querySelector('.query-field'); if (field) field.placeholder = `Search Query ${idx + 1}`; }); }; // Search button const searchButton = document.createElement('button'); searchButton.type = 'button'; searchButton.className = 'action-button search-button'; searchButton.textContent = 'Search'; searchButton.onclick = function() { performSearch(queryField.value, queryItem); }; // Add elements to container queryContainer.appendChild(queryField); queryContainer.appendChild(searchButton); queryContainer.appendChild(deleteButton); // Create loading indicator for this search const searchLoading = document.createElement('div'); searchLoading.className = 'search-loading'; searchLoading.textContent = 'Searching... Please wait.'; // Create table for results const resultsTable = document.createElement('table'); resultsTable.className = 'results-table'; // Add table header const tableHeader = document.createElement('thead'); const headerRow = document.createElement('tr'); const typeHeader = document.createElement('th'); typeHeader.textContent = 'Type'; const titleHeader = document.createElement('th'); titleHeader.textContent = 'Title'; const bodyHeader = document.createElement('th'); bodyHeader.textContent = 'Description'; const urlHeader = document.createElement('th'); urlHeader.textContent = 'URL'; const scoreHeader = document.createElement('th'); scoreHeader.textContent = 'Score'; const justificationHeader = document.createElement('th'); justificationHeader.textContent = 'Justification'; headerRow.appendChild(typeHeader); headerRow.appendChild(titleHeader); headerRow.appendChild(bodyHeader); headerRow.appendChild(urlHeader); headerRow.appendChild(scoreHeader); headerRow.appendChild(justificationHeader); tableHeader.appendChild(headerRow); // Add table body const tableBody = document.createElement('tbody'); resultsTable.appendChild(tableHeader); resultsTable.appendChild(tableBody); // Add all elements to the query item queryItem.appendChild(queryContainer); queryItem.appendChild(searchLoading); queryItem.appendChild(resultsTable); // Add container to the queries list queriesContainer.appendChild(queryItem); } function createAccordionSection(timestamp) { const accordionSection = document.createElement('div'); accordionSection.className = 'accordion-section'; const accordionHeader = document.createElement('div'); accordionHeader.className = 'accordion-header'; accordionHeader.innerHTML = ` Search Results ${timestamp} `; accordionHeader.onclick = function() { this.classList.toggle('collapsed'); const body = this.nextElementSibling; body.classList.toggle('collapsed'); // Update the toggle icon const toggleIcon = this.querySelector('.toggle-icon'); if (body.classList.contains('collapsed')) { toggleIcon.textContent = '▶'; } else { toggleIcon.textContent = '▼'; } }; const accordionBody = document.createElement('div'); accordionBody.className = 'accordion-body'; const accordionContent = document.createElement('div'); accordionContent.className = 'accordion-content'; accordionBody.appendChild(accordionContent); accordionSection.appendChild(accordionHeader); accordionSection.appendChild(accordionBody); return accordionSection; } const userInput = document.getElementById('userProblemDescription').value.trim(); if (!userInput) { alert('Please enter a technical problem description'); return; } // Show loading indicator document.getElementById('loadingIndicator').style.display = 'block'; // Collapse all existing query sections const existingAccordions = document.querySelectorAll('.accordion-section'); existingAccordions.forEach(accordion => { const header = accordion.querySelector('.accordion-header'); const body = accordion.querySelector('.accordion-body'); if (header && body && !header.classList.contains('collapsed')) { header.classList.add('collapsed'); body.classList.add('collapsed'); } }); // Send message to Flask backend fetch('/chat', { method: 'POST', body: new URLSearchParams({ 'message': userInput }), headers: { 'Content-Type': 'application/x-www-form-urlencoded' } }) .then(response => response.json()) .then(data => { // Hide loading indicator document.getElementById('loadingIndicator').style.display = 'none'; try { // Parse the JSON string from the LLM response let jsonData; // First check if data.reply is already an object if (typeof data.reply === 'object') { jsonData = data.reply; } else { // Try to extract JSON if it's a string possibly with markdown code blocks const jsonString = data.reply.replace(/```json|```/g, '').trim(); jsonData = JSON.parse(jsonString); } // Create a new accordion section for these search results const timestamp = new Date().toLocaleString(); const accordionSection = createAccordionSection(timestamp); // Add each query from the response to this accordion Object.keys(jsonData).forEach(key => { addQueryField(jsonData[key], accordionSection.querySelector('.accordion-content')); }); // Add the accordion to the container const queriesContainer = document.getElementById('queriesContainer'); queriesContainer.insertBefore(accordionSection, queriesContainer.firstChild); // Show results container document.getElementById('resultsContainer').style.display = 'block'; } catch (error) { console.error('Error parsing JSON:', error); alert('There was an error processing the response. Please try again.'); } }) .catch(error => { document.getElementById('loadingIndicator').style.display = 'none'; console.error('Error:', error); alert('There was an error communicating with the server. Please try again.'); }); } function displayKeyIssues(keyIssues) { // Get or create the key issues container let keyIssuesContainer = document.getElementById('keyIssuesContainer'); if (!keyIssuesContainer) { keyIssuesContainer = document.createElement('div'); keyIssuesContainer.id = 'keyIssuesContainer'; keyIssuesContainer.className = 'key-issues-container'; document.getElementById('resultsContainer').appendChild(keyIssuesContainer); } // Clear previous content keyIssuesContainer.innerHTML = ''; // Create header const header = document.createElement('h3'); header.textContent = 'Key Issues'; keyIssuesContainer.appendChild(header); // Create issues list const issuesList = document.createElement('div'); issuesList.className = 'key-issues-list'; const KIsubmitButton = document.createElement('button'); KIsubmitButton.className = "btn btn-primary"; KIsubmitButton.id = "key-issues-submit-btn"; KIsubmitButton.textContent = "Generate problem descriptions"; KIsubmitButton.style.marginTop = "10px"; KIsubmitButton.onclick = generateProblemDescriptions; const centerButton = document.createElement("center"); centerButton.appendChild(KIsubmitButton); // Add each key issue keyIssues.forEach(issue => { const issueCard = document.createElement('div'); issueCard.className = 'key-issue-card'; issueCard.dataset.id = issue.id; const issueTitle = document.createElement('div'); issueTitle.className = 'key-issue-title'; issueTitle.textContent = issue.title; const issueDescription = document.createElement('div'); issueDescription.className = 'key-issue-description'; issueDescription.textContent = issue.description; const challengesTitle = document.createElement('div'); challengesTitle.style.fontWeight = 'bold'; challengesTitle.style.marginTop = '10px'; challengesTitle.textContent = 'Challenges:'; const challengesList = document.createElement('ul'); challengesList.className = 'key-issue-challenges'; issue.challenges.forEach(challenge => { const challengeItem = document.createElement('li'); challengeItem.textContent = challenge; challengesList.appendChild(challengeItem); }); const impactTitle = document.createElement('div'); impactTitle.style.fontWeight = 'bold'; impactTitle.style.marginTop = '10px'; impactTitle.textContent = 'Potential Impact:'; const issueImpact = document.createElement('div'); issueImpact.className = 'key-issue-impact'; issueImpact.textContent = issue.potential_impact; // Add click handler to toggle selection issueCard.addEventListener('click', function() { this.classList.toggle('selected'); }); // Append all elements issueCard.appendChild(issueTitle); issueCard.appendChild(issueDescription); issueCard.appendChild(challengesTitle); issueCard.appendChild(challengesList); issueCard.appendChild(impactTitle); issueCard.appendChild(issueImpact); issuesList.appendChild(issueCard); }); keyIssuesContainer.appendChild(issuesList); keyIssuesContainer.appendChild(centerButton); keyIssuesContainer.style.display = "block"; } function generateProblemDescriptions(){ let result = { descriptions: {}, challenges: {} }; const selectedCards = document.querySelectorAll(".key-issue-card.selected"); selectedCards.forEach(card => { const userInput = document.getElementById('userInput').value.trim(); const id = card.getAttribute("data-id"); const description = card.querySelector('.key-issue-description').textContent.trim(); const challenges = Array.from(card.querySelectorAll(".key-issue-challenges li")).map(challenge => challenge.textContent.trim()); result.descriptions[id] = description; result.challenges[id] = challenges; result["technical_topic"] = userInput; }) document.querySelector('.progress-text').innerHTML = "Generating problem descriptions ... This may take a while." document.getElementById('globalLoadingOverlay').style.display = 'flex'; // Send message to Flask backend fetch('/create-several-probdesc', { method: 'POST', body: JSON.stringify(result), headers: { 'Content-Type': 'application/json' } }) .then(response => response.json()) .then(data => { // Hide loading indicator document.getElementById('globalLoadingOverlay').style.display = 'none'; // Check if we have key issues in the response if (data.problem_descriptions && data.problem_descriptions.length > 0) { // Display the key issues displayProblemDescriptions(data.problem_descriptions); } else if (data.error) { alert('Error: ' + data.error); } else { alert('No problem descriptions found/generated. Please try again with another or the same query.'); } }) .catch(error => { document.getElementById('globalLoadingOverlay').style.display = 'none'; console.error('Error:', error); alert('There was an error communicating with the server. Please try again.'); }); } function displayProblemDescriptions(probDescs) { // Get or create the key issues container let probDescCards = document.getElementById("probDescCards"); let probDescContainer = document.getElementById('probDescContainer'); // Clear previous content probDescContainer.innerHTML = ''; // Create header const header = document.createElement('h3'); header.textContent = 'Problem Descriptions'; probDescContainer.appendChild(header); // Create issues list const descriptionList = document.createElement('div'); descriptionList.className = 'prob-desc-list'; // Add each key issue probDescs.forEach((desc, index) => { const descCard = document.createElement('div'); descCard.className = 'prob-desc-card'; descCard.dataset.id = index+1; const descTitle = document.createElement('div'); descTitle.className = 'prob-desc-title'; descTitle.textContent = `Problem Description n°${index+1}`; const descDescription = document.createElement('div'); descDescription.className = 'prob-desc-description'; descDescription.textContent = desc; // Add click handler to toggle selection descCard.addEventListener('click', function() { document.getElementById("userProblemDescription").textContent = desc; document.getElementsByClassName("tablinks")[1].click(); }); // Append all elements descCard.appendChild(descTitle); descCard.appendChild(descDescription); descriptionList.appendChild(descCard); }); probDescContainer.appendChild(descriptionList); probDescCards.style.display = "block"; } function initRibbonAccordion() { const ribbon = document.querySelector('.ribbon-accordion'); const ribbonHeader = ribbon.querySelector('.ribbon-header'); ribbonHeader.addEventListener('click', function() { ribbon.classList.toggle('collapsed'); }); } function setupRibbonButtons() { // Generate Queries document.getElementById('ribbonGenerateQueriesButton').addEventListener('click', function() { generateSearchQueries(); }); // Analyze All document.getElementById('ribbonAnalyzeAllButton').addEventListener('click', function() { if(hasSearchResults()) { analyzeAllPapers(); } }); // Remove Failed document.getElementById('ribbonRemoveFailedButton').addEventListener('click', function() { if(hasSearchResults()) { removeFailedAnalyses(); } }); // Extract All Insights document.getElementById('ribbonExtractAllInsightsButton').addEventListener('click', function() { extractAllInsights(); }); // Group Insights document.getElementById('ribbonGroupInsightsButton').addEventListener('click', function() { groupInsightsByScore(); }); // Enhance Problem document.getElementById('ribbonEnhanceProblemButton').addEventListener('click', function() { enhanceProblem(); }); // Export to Excel document.getElementById('ribbonExportExcelButton').addEventListener('click', function() { if(hasSearchResults()) { exportToExcel(); } }); } initRibbonAccordion(); setupRibbonButtons();