document.addEventListener('DOMContentLoaded', function() { const chatContainer = document.getElementById('chat-container'); const followUpContainer = document.getElementById('follow-up-container'); const userInput = document.getElementById('user-input'); const sendButton = document.getElementById('send-button'); const statusIndicator = document.getElementById('status-indicator'); const leftPanel = document.querySelector('.left-panel'); const rightPanel = document.querySelector('.right-panel'); const resizer = document.getElementById('resizer'); const splitScreen = document.querySelector('.split-screen'); let isResizing = false; resizer.addEventListener('mousedown', initResize); document.addEventListener('mousemove', resize); document.addEventListener('mouseup', stopResize); function initResize(e) { isResizing = true; document.body.style.cursor = 'col-resize'; } function resize(e) { if (!isResizing) return; const containerWidth = splitScreen.offsetWidth; const newLeftWidth = e.clientX - leftPanel.offsetLeft; const newRightWidth = containerWidth - newLeftWidth - resizer.offsetWidth; if (newLeftWidth > 300 && newRightWidth > 300) { const leftPercentage = (newLeftWidth / containerWidth) * 100; const rightPercentage = (newRightWidth / containerWidth) * 100; document.documentElement.style.setProperty('--chat-width', `${leftPercentage}%`); document.documentElement.style.setProperty('--pdf-width', `${rightPercentage}%`); } } function stopResize() { isResizing = false; document.body.style.cursor = 'default'; } function updateStatus() { fetch('/status') .then(response => response.json()) .then(data => { const statusBulb = document.getElementById('status-bulb'); statusIndicator.title = data.status; statusBulb.style.backgroundColor = data.status.includes("Connected") ? "green" : "red"; }); } function sendMessage() { const question = userInput.value.trim(); if (question) { addMessage('user', question); userInput.value = ''; clearFollowUpQuestions(); showSearchingIndicator(); fetch('/ask', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ question: question }), }) .then(response => response.json()) .then(data => { removeSearchingIndicator(); addMessage('bot', data.response); addSources(data.sources); if (data.follow_up_questions) { setTimeout(() => { addFollowUpQuestions(data.follow_up_questions); }, 1000); } }) .catch(error => { console.error('Error:', error); removeSearchingIndicator(); addMessage('bot', 'Sorry, there was an error processing your request.'); }); } } function addMessage(sender, message) { const messageElement = document.createElement('div'); messageElement.className = `${sender}-message message`; messageElement.textContent = message; chatContainer.appendChild(messageElement); scrollToBottom(); } function showSearchingIndicator() { const searchingElement = document.createElement('div'); searchingElement.className = 'bot-message message searching'; searchingElement.textContent = 'Searching'; searchingElement.id = 'searching-indicator'; chatContainer.appendChild(searchingElement); scrollToBottom(); } function removeSearchingIndicator() { const searchingElement = document.getElementById('searching-indicator'); if (searchingElement) { searchingElement.remove(); } } function addSources(sources) { console.log("Raw sources:", sources); // Log the raw sources string if (sources && sources.trim() !== "") { const sourcesElement = document.createElement('div'); sourcesElement.className = 'sources'; sourcesElement.innerHTML = 'Sources:
'; const sourcesList = sources.split(/(?=\d+\.\s+(?:Text|Image Description) from)/).filter(Boolean); console.log("Split sources:", sourcesList); // Log the split sources sourcesList.forEach((source) => { const sourceInfo = parseSourceInfo(source.trim()); if (sourceInfo) { const sourceLink = document.createElement('a'); sourceLink.href = '#'; sourceLink.textContent = `${sourceInfo.index}. ${sourceInfo.type} from ${sourceInfo.fileName} (Page ${sourceInfo.page}${sourceInfo.additional ? ', ' + sourceInfo.additional : ''})`; sourceLink.onclick = function(e) { e.preventDefault(); openSource(sourceInfo); }; sourcesElement.appendChild(sourceLink); sourcesElement.appendChild(document.createElement('br')); } }); chatContainer.appendChild(sourcesElement); scrollToBottom(); } else { console.log("No sources provided or empty sources string"); // Log if sources is empty } } function addFollowUpQuestions(questions) { clearFollowUpQuestions(); if (followUpContainer && questions && questions.length > 0) { questions.forEach((question, index) => { const button = document.createElement('button'); button.textContent = `${index + 1}. ${question}`; button.className = 'follow-up-button'; button.addEventListener('click', () => { userInput.value = question; sendMessage(); }); followUpContainer.appendChild(button); }); } } function clearFollowUpQuestions() { followUpContainer.innerHTML = ''; } function scrollToBottom() { chatContainer.scrollTop = chatContainer.scrollHeight; } function parseSourceInfo(source) { console.log("parseSourceInfo input:", source); const regex = /(\d+)\.\s+(Text|Image Description) from (.*?\.pdf)(?:\s+\(Page (\d+)(?:,\s*(.+))?\))?/; const match = source.match(regex); if (match) { const result = { index: match[1], type: match[2], fileName: match[3], page: match[4] || '1', additional: match[5] || '' }; console.log("parseSourceInfo output:", result); return result; } else { console.log("parseSourceInfo failed to match regex"); return null; } } function openSource(sourceInfo) { if (sourceInfo) { const viewerContainer = document.getElementById('viewer-container'); if (!viewerContainer) { return; } viewerContainer.innerHTML = ''; const url = `/data/${encodeURIComponent(sourceInfo.fileName)}#page=${sourceInfo.page}`; const pdfViewer = document.createElement('iframe'); pdfViewer.id = 'pdf-viewer'; pdfViewer.src = url; const closeButton = document.createElement('button'); closeButton.id = 'close-pdf'; closeButton.textContent = 'Close'; closeButton.onclick = closePDFViewer; viewerContainer.appendChild(closeButton); viewerContainer.appendChild(pdfViewer); openPDFViewer(); } } function openPDFViewer() { document.documentElement.style.setProperty('--chat-width', '50%'); document.documentElement.style.setProperty('--pdf-width', '50%'); rightPanel.style.display = 'flex'; resizer.style.display = 'block'; } function closePDFViewer() { document.documentElement.style.setProperty('--chat-width', '100%'); document.documentElement.style.setProperty('--pdf-width', '0%'); setTimeout(() => { rightPanel.style.display = 'none'; resizer.style.display = 'none'; }, 300); // Wait for transition to complete } function adjustPanelSizes() { const totalWidth = splitScreen.offsetWidth; if (rightPanel.style.display !== 'none') { document.documentElement.style.setProperty('--chat-width', '50%'); document.documentElement.style.setProperty('--pdf-width', '50%'); } else { document.documentElement.style.setProperty('--chat-width', '100%'); document.documentElement.style.setProperty('--pdf-width', '0%'); } } sendButton.addEventListener('click', sendMessage); userInput.addEventListener('keypress', function(e) { if (e.key === 'Enter' && !e.shiftKey) { e.preventDefault(); sendMessage(); } }); window.addEventListener('resize', adjustPanelSizes); updateStatus(); setInterval(updateStatus, 5000); // Initially hide the right panel and resizer rightPanel.style.display = 'none'; resizer.style.display = 'none'; document.documentElement.style.setProperty('--chat-width', '100%'); document.documentElement.style.setProperty('--pdf-width', '0%'); function checkConnection() { fetch('/check_connection') .then(response => response.json()) .then(data => { updateConnectionStatus(data.status, data.color); }) .catch(error => console.error('Error:', error)); } // Check connection every 30 seconds setInterval(checkConnection, 30000); // Also check connection when the page loads document.addEventListener('DOMContentLoaded', checkConnection); function updateConnectionStatus() { fetch('/status') .then(response => response.json()) .then(data => { const statusElement = document.getElementById('connection-status'); const userInput = document.getElementById('user-input'); const sendButton = document.getElementById('send-button'); if (statusElement) { statusElement.textContent = data.status; statusElement.style.color = data.color; } else { console.warn('Status element not found'); } if (userInput && sendButton) { if (data.status !== "Connected") { userInput.disabled = true; sendButton.disabled = true; userInput.placeholder = "Chat is disabled. Weaviate is not connected."; } else { userInput.disabled = false; sendButton.disabled = false; userInput.placeholder = "Type your message here..."; } } else { console.warn('Chat input or send button not found'); } }) .catch(error => { console.error('Error updating connection status:', error); }); } // Call this function when the page loads and periodically document.addEventListener('DOMContentLoaded', () => { updateConnectionStatus(); setInterval(updateConnectionStatus, 5000); // Check every 5 seconds }); let chatHistory = []; function sendMessage() { const userInput = document.getElementById('user-input'); const message = userInput.value.trim(); if (message) { addMessageToChat('You', message); userInput.value = ''; fetchResponse(message); } } function addMessageToChat(sender, message) { const chatMessages = document.getElementById('chat-messages'); const messageElement = document.createElement('div'); messageElement.innerHTML = `${sender}: ${message}`; chatMessages.appendChild(messageElement); chatMessages.scrollTop = chatMessages.scrollHeight; } function fetchResponse(message) { fetch('/ask', { method: 'POST', headers: { 'Content-Type': 'application/json', }, body: JSON.stringify({ question: message }), }) .then(response => response.json()) .then(data => { addMessageToChat('AI', data.response); updateHistory(message, data.response, data.sources); fetchAndDisplayHistory(); }) .catch(error => { console.error('Error:', error); addMessageToChat('AI', 'Sorry, an error occurred while processing your request.'); }); } function updateHistory(question, answer, sources) { chatHistory.push({ question, answer, sources }); if (chatHistory.length > 10) { chatHistory.shift(); } } function fetchAndDisplayHistory() { const historyList = document.getElementById('history-list'); historyList.innerHTML = ''; chatHistory.forEach((item, index) => { const historyItem = document.createElement('div'); historyItem.className = 'history-item'; historyItem.innerHTML = `

Question ${index + 1}

Q: ${item.question}

A: ${item.answer}

Sources: ${item.sources || 'N/A'}

`; historyList.appendChild(historyItem); }); } // Initialize history on page load fetchAndDisplayHistory(); });