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 = `
Q: ${item.question}
A: ${item.answer}
Sources: ${item.sources || 'N/A'}
`; historyList.appendChild(historyItem); }); } // Initialize history on page load fetchAndDisplayHistory(); });