Spaces:
Sleeping
Sleeping
| document.addEventListener('DOMContentLoaded', function() { | |
| const chatForm = document.getElementById('chat-form'); | |
| const messageInput = document.getElementById('message-input'); | |
| const chatMessages = document.getElementById('chat-messages'); | |
| const sendButton = document.getElementById('send-button'); | |
| const loadingIndicator = document.getElementById('loading'); | |
| const suggestionButtons = document.querySelectorAll('.suggestion-btn'); | |
| const clearButton = document.getElementById('clear-chat'); | |
| const exportButton = document.getElementById('export-chat'); | |
| let conversationHistory = []; | |
| // Character counter for message input | |
| const maxChars = 1000; | |
| const charCounter = document.createElement('div'); | |
| charCounter.className = 'char-counter'; | |
| charCounter.textContent = `0/${maxChars}`; | |
| messageInput.parentNode.appendChild(charCounter); | |
| messageInput.addEventListener('input', function() { | |
| const currentLength = this.value.length; | |
| charCounter.textContent = `${currentLength}/${maxChars}`; | |
| charCounter.style.color = currentLength > maxChars * 0.9 ? '#e74c3c' : '#666'; | |
| // Enable/disable send button based on input | |
| sendButton.disabled = currentLength === 0 || currentLength > maxChars; | |
| }); | |
| // Handle suggestion button clicks | |
| suggestionButtons.forEach(button => { | |
| button.addEventListener('click', function() { | |
| const suggestion = this.textContent; | |
| messageInput.value = suggestion; | |
| messageInput.focus(); | |
| messageInput.dispatchEvent(new Event('input')); | |
| }); | |
| }); | |
| // Handle form submission | |
| chatForm.addEventListener('submit', function(e) { | |
| e.preventDefault(); | |
| const message = messageInput.value.trim(); | |
| if (message && message.length <= maxChars) { | |
| sendMessage(message); | |
| } | |
| }); | |
| // Clear chat functionality | |
| if (clearButton) { | |
| clearButton.addEventListener('click', function() { | |
| if (confirm('Are you sure you want to clear the chat history?')) { | |
| chatMessages.innerHTML = ''; | |
| conversationHistory = []; | |
| addSystemMessage('Chat cleared. How can I help you with company policies?'); | |
| } | |
| }); | |
| } | |
| // Export chat functionality | |
| if (exportButton) { | |
| exportButton.addEventListener('click', function() { | |
| exportChatHistory(); | |
| }); | |
| } | |
| function sendMessage(message) { | |
| // Add user message to chat | |
| addMessage(message, 'user'); | |
| // Clear input and show loading | |
| messageInput.value = ''; | |
| charCounter.textContent = `0/${maxChars}`; | |
| sendButton.disabled = true; | |
| showLoading(true); | |
| // Send to backend | |
| fetch('/chat', { | |
| method: 'POST', | |
| headers: { | |
| 'Content-Type': 'application/json', | |
| }, | |
| body: JSON.stringify({ | |
| message: message, | |
| conversation_history: conversationHistory | |
| }) | |
| }) | |
| .then(response => { | |
| if (!response.ok) { | |
| throw new Error(`HTTP error! status: ${response.status}`); | |
| } | |
| return response.json(); | |
| }) | |
| .then(data => { | |
| showLoading(false); | |
| if (data.response) { | |
| addMessage(data.response, 'assistant', data.sources); | |
| // Update conversation history | |
| conversationHistory.push({ | |
| user: message, | |
| assistant: data.response | |
| }); | |
| // Limit conversation history to last 10 exchanges | |
| if (conversationHistory.length > 10) { | |
| conversationHistory = conversationHistory.slice(-10); | |
| } | |
| } else { | |
| addSystemMessage('Sorry, I encountered an error processing your request. Please try again.'); | |
| } | |
| }) | |
| .catch(error => { | |
| console.error('Error:', error); | |
| showLoading(false); | |
| addSystemMessage('Sorry, there was a connection error. Please check your internet connection and try again.'); | |
| }); | |
| } | |
| function addMessage(content, sender, sources = null) { | |
| const messageDiv = document.createElement('div'); | |
| messageDiv.className = `message ${sender}-message`; | |
| const messageContent = document.createElement('div'); | |
| messageContent.className = 'message-content'; | |
| messageContent.textContent = content; | |
| const timestamp = document.createElement('div'); | |
| timestamp.className = 'message-timestamp'; | |
| timestamp.textContent = new Date().toLocaleTimeString(); | |
| messageDiv.appendChild(messageContent); | |
| messageDiv.appendChild(timestamp); | |
| // Add sources if provided | |
| if (sources && sources.length > 0) { | |
| const sourcesDiv = document.createElement('div'); | |
| sourcesDiv.className = 'message-sources'; | |
| sourcesDiv.innerHTML = '<strong>Sources:</strong>'; | |
| sources.forEach((source, index) => { | |
| const sourceSpan = document.createElement('span'); | |
| sourceSpan.className = 'source-tag'; | |
| sourceSpan.textContent = `${source.filename} (${Math.round(source.score * 100)}% relevant)`; | |
| sourceSpan.title = `Chunk: ${source.chunk_id}\nScore: ${source.score.toFixed(3)}`; | |
| sourcesDiv.appendChild(sourceSpan); | |
| }); | |
| messageDiv.appendChild(sourcesDiv); | |
| } | |
| chatMessages.appendChild(messageDiv); | |
| chatMessages.scrollTop = chatMessages.scrollHeight; | |
| } | |
| function addSystemMessage(content) { | |
| const messageDiv = document.createElement('div'); | |
| messageDiv.className = 'message system-message'; | |
| const messageContent = document.createElement('div'); | |
| messageContent.className = 'message-content'; | |
| messageContent.textContent = content; | |
| messageDiv.appendChild(messageContent); | |
| chatMessages.appendChild(messageDiv); | |
| chatMessages.scrollTop = chatMessages.scrollHeight; | |
| } | |
| function showLoading(show) { | |
| if (loadingIndicator) { | |
| loadingIndicator.style.display = show ? 'block' : 'none'; | |
| } | |
| sendButton.disabled = show; | |
| } | |
| function exportChatHistory() { | |
| if (conversationHistory.length === 0) { | |
| alert('No conversation history to export.'); | |
| return; | |
| } | |
| let exportText = 'PolicyWise Chat Export\n'; | |
| exportText += '======================\n'; | |
| exportText += `Exported on: ${new Date().toLocaleString()}\n\n`; | |
| conversationHistory.forEach((exchange, index) => { | |
| exportText += `--- Exchange ${index + 1} ---\n`; | |
| exportText += `User: ${exchange.user}\n`; | |
| exportText += `Assistant: ${exchange.assistant}\n\n`; | |
| }); | |
| const blob = new Blob([exportText], { type: 'text/plain' }); | |
| const url = URL.createObjectURL(blob); | |
| const a = document.createElement('a'); | |
| a.href = url; | |
| a.download = `policywise-chat-${new Date().toISOString().split('T')[0]}.txt`; | |
| document.body.appendChild(a); | |
| a.click(); | |
| document.body.removeChild(a); | |
| URL.revokeObjectURL(url); | |
| } | |
| // Initialize with welcome message | |
| addSystemMessage('Hello! I\'m PolicyWise, your intelligent policy assistant. I can help you find information from our company policy documents. What would you like to know?'); | |
| // Focus on input field | |
| messageInput.focus(); | |
| // Handle keyboard shortcuts | |
| document.addEventListener('keydown', function(e) { | |
| // Ctrl/Cmd + Enter to send message | |
| if ((e.ctrlKey || e.metaKey) && e.key === 'Enter') { | |
| if (messageInput.value.trim()) { | |
| chatForm.dispatchEvent(new Event('submit')); | |
| } | |
| } | |
| // Escape to clear input | |
| if (e.key === 'Escape') { | |
| messageInput.value = ''; | |
| messageInput.dispatchEvent(new Event('input')); | |
| messageInput.focus(); | |
| } | |
| }); | |
| }); | |