Fix upload 'processing' status
This commit is contained in:
104
views/chat.ejs
104
views/chat.ejs
@@ -5,23 +5,16 @@
|
||||
<div class="col-lg-8">
|
||||
<div class="card shadow-lg border-0 chat">
|
||||
<div class="card-header bg-primary text-white">
|
||||
<h3 class="mb-0"><i class="fas fa-comments me-2"></i>Chat with EduCat AI</h3>
|
||||
<div class="d-flex justify-content-between align-items-center">
|
||||
<h3 class="mb-0"><i class="fas fa-comments me-2"></i>Chat with EduCat AI</h3>
|
||||
<button type="button" id="clear-chat-btn" class="btn btn-outline-light btn-sm" title="Clear Chat History">
|
||||
<i class="fas fa-trash-alt me-1"></i>Clear
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="card-body p-0">
|
||||
<div id="chat-container" class="p-4" style="height: 500px; overflow-y: auto;">
|
||||
<div class="chat-message bot-message mb-3">
|
||||
<div class="d-flex align-items-start">
|
||||
<div class="avatar bg-primary text-white rounded-circle d-flex align-items-center justify-content-center me-3 flex-shrink-0" style="width: 45px; height: 45px; min-width: 45px;">
|
||||
<i class="fas fa-cat" style="font-size: 1.2rem;"></i>
|
||||
</div>
|
||||
<div class="message-content flex-grow-1">
|
||||
<div class="message-bubble bg-light p-3 rounded-3 shadow-sm border">
|
||||
<p class="mb-0">Hello! I'm EduCat AI, your study assistant. I can help you with questions about your notes, study techniques, and academic topics. How can I assist you today?</p>
|
||||
</div>
|
||||
<small class="text-muted d-block mt-1">Just now</small>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<!-- Initial bot message will be added here if no history exists -->
|
||||
</div>
|
||||
<div class="border-top bg-light p-3">
|
||||
<div class="input-group">
|
||||
@@ -59,12 +52,17 @@
|
||||
</div>
|
||||
|
||||
<script>
|
||||
let chatHistory = [];
|
||||
// Get chat history from server-side rendered data
|
||||
const serverChatHistory = <%- JSON.stringify(chatHistory || []) %>;
|
||||
|
||||
document.addEventListener('DOMContentLoaded', function() {
|
||||
const chatContainer = document.getElementById('chat-container');
|
||||
const chatInput = document.getElementById('chat-input');
|
||||
const sendBtn = document.getElementById('send-btn');
|
||||
const clearChatBtn = document.getElementById('clear-chat-btn');
|
||||
|
||||
// Load existing chat history from server
|
||||
loadChatHistory();
|
||||
|
||||
sendBtn.addEventListener('click', sendMessage);
|
||||
chatInput.addEventListener('keypress', function(e) {
|
||||
@@ -73,6 +71,45 @@ document.addEventListener('DOMContentLoaded', function() {
|
||||
}
|
||||
});
|
||||
|
||||
clearChatBtn.addEventListener('click', clearChatHistory);
|
||||
|
||||
function loadChatHistory() {
|
||||
// Clear the container first
|
||||
chatContainer.innerHTML = '';
|
||||
|
||||
if (serverChatHistory.length === 0) {
|
||||
// Show initial welcome message if no history exists
|
||||
addWelcomeMessage();
|
||||
} else {
|
||||
// Load all previous messages
|
||||
serverChatHistory.forEach(conversation => {
|
||||
addMessageToChat('user', conversation.human, false);
|
||||
addMessageToChat('bot', conversation.ai, false);
|
||||
});
|
||||
}
|
||||
|
||||
chatContainer.scrollTop = chatContainer.scrollHeight;
|
||||
}
|
||||
|
||||
function addWelcomeMessage() {
|
||||
const messageDiv = document.createElement('div');
|
||||
messageDiv.className = 'chat-message bot-message mb-3';
|
||||
messageDiv.innerHTML = `
|
||||
<div class="d-flex align-items-start">
|
||||
<div class="avatar bg-primary text-white rounded-circle d-flex align-items-center justify-content-center me-3 flex-shrink-0" style="width: 45px; height: 45px; min-width: 45px;">
|
||||
<i class="fas fa-cat" style="font-size: 1.2rem;"></i>
|
||||
</div>
|
||||
<div class="message-content flex-grow-1">
|
||||
<div class="message-bubble bg-light p-3 rounded-3 shadow-sm border">
|
||||
<p class="mb-0">Hello! I'm EduCat AI, your study assistant. I can help you with questions about your notes, study techniques, and academic topics. How can I assist you today?</p>
|
||||
</div>
|
||||
<small class="text-muted d-block mt-1">Just now</small>
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
chatContainer.appendChild(messageDiv);
|
||||
}
|
||||
|
||||
function sendMessage() {
|
||||
const message = chatInput.value.trim();
|
||||
if (!message) return;
|
||||
@@ -88,8 +125,7 @@ document.addEventListener('DOMContentLoaded', function() {
|
||||
sendToAI(message);
|
||||
}
|
||||
|
||||
function addMessageToChat(sender, message) {
|
||||
const chatContainer = document.getElementById('chat-container');
|
||||
function addMessageToChat(sender, message, withScroll = true) {
|
||||
const messageDiv = document.createElement('div');
|
||||
messageDiv.className = `chat-message ${sender}-message mb-3`;
|
||||
|
||||
@@ -126,11 +162,12 @@ document.addEventListener('DOMContentLoaded', function() {
|
||||
}
|
||||
|
||||
chatContainer.appendChild(messageDiv);
|
||||
chatContainer.scrollTop = chatContainer.scrollHeight;
|
||||
if (withScroll) {
|
||||
chatContainer.scrollTop = chatContainer.scrollHeight;
|
||||
}
|
||||
}
|
||||
|
||||
function addTypingIndicator() {
|
||||
const chatContainer = document.getElementById('chat-container');
|
||||
const typingDiv = document.createElement('div');
|
||||
typingDiv.id = 'typing-indicator';
|
||||
typingDiv.className = 'chat-message bot-message mb-3';
|
||||
@@ -170,8 +207,7 @@ document.addEventListener('DOMContentLoaded', function() {
|
||||
'Content-Type': 'application/json',
|
||||
},
|
||||
body: JSON.stringify({
|
||||
message: message,
|
||||
history: chatHistory
|
||||
message: message
|
||||
})
|
||||
});
|
||||
|
||||
@@ -181,7 +217,6 @@ document.addEventListener('DOMContentLoaded', function() {
|
||||
|
||||
if (result.success) {
|
||||
addMessageToChat('bot', result.response);
|
||||
chatHistory.push({human: message, ai: result.response});
|
||||
} else {
|
||||
addMessageToChat('bot', 'Sorry, I encountered an error. Please try again.');
|
||||
}
|
||||
@@ -190,6 +225,31 @@ document.addEventListener('DOMContentLoaded', function() {
|
||||
addMessageToChat('bot', 'Sorry, I\'m having trouble connecting right now. Please try again.');
|
||||
}
|
||||
}
|
||||
|
||||
async function clearChatHistory() {
|
||||
if (!confirm('Are you sure you want to clear the chat history? This action cannot be undone.')) {
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
const response = await fetch('/api/chat/history', {
|
||||
method: 'DELETE'
|
||||
});
|
||||
|
||||
const result = await response.json();
|
||||
|
||||
if (result.success) {
|
||||
// Clear the chat container and show welcome message
|
||||
chatContainer.innerHTML = '';
|
||||
addWelcomeMessage();
|
||||
chatContainer.scrollTop = chatContainer.scrollHeight;
|
||||
} else {
|
||||
alert('Failed to clear chat history. Please try again.');
|
||||
}
|
||||
} catch (error) {
|
||||
alert('Error clearing chat history. Please try again.');
|
||||
}
|
||||
}
|
||||
});
|
||||
</script>
|
||||
|
||||
|
||||
@@ -5,9 +5,14 @@
|
||||
<div class="col-12">
|
||||
<div class="d-flex justify-content-between align-items-center mb-4">
|
||||
<h2><i class="fas fa-tachometer-alt me-2"></i>Your Dashboard</h2>
|
||||
<a href="/upload" class="btn btn-primary">
|
||||
<i class="fas fa-plus me-2"></i>Upload New Notes
|
||||
</a>
|
||||
<div>
|
||||
<button class="btn btn-outline-secondary me-2" onclick="refreshStatus()" id="refreshBtn">
|
||||
<i class="fas fa-sync-alt me-1"></i>Refresh Status
|
||||
</button>
|
||||
<a href="/upload" class="btn btn-primary">
|
||||
<i class="fas fa-plus me-2"></i>Upload New Notes
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<% if (files.length === 0) { %>
|
||||
@@ -497,6 +502,49 @@ async function viewProcessingDetails(fileId) {
|
||||
// Progress monitoring for processing files
|
||||
let progressMonitoring = {};
|
||||
|
||||
// Manual refresh function
|
||||
async function refreshStatus() {
|
||||
const refreshBtn = document.getElementById('refreshBtn');
|
||||
const originalHtml = refreshBtn.innerHTML;
|
||||
|
||||
refreshBtn.innerHTML = '<i class="fas fa-spinner fa-spin me-1"></i>Refreshing...';
|
||||
refreshBtn.disabled = true;
|
||||
|
||||
try {
|
||||
const response = await fetch('/api/files/status/all');
|
||||
const result = await response.json();
|
||||
|
||||
if (result.success) {
|
||||
console.log('Status refresh successful:', result.summary);
|
||||
|
||||
// Check if status has changed - if so, reload page to show updates
|
||||
const hasProcessingFiles = result.summary.processing > 0;
|
||||
const currentProcessingBadges = document.querySelectorAll('.badge').length;
|
||||
|
||||
if (!hasProcessingFiles || result.summary.processed > 0) {
|
||||
console.log('Status changed, reloading page...');
|
||||
location.reload();
|
||||
} else {
|
||||
// Show success feedback
|
||||
refreshBtn.innerHTML = '<i class="fas fa-check me-1"></i>Updated';
|
||||
setTimeout(() => {
|
||||
refreshBtn.innerHTML = originalHtml;
|
||||
refreshBtn.disabled = false;
|
||||
}, 1500);
|
||||
}
|
||||
} else {
|
||||
throw new Error(result.error || 'Failed to refresh status');
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('Error refreshing status:', error);
|
||||
refreshBtn.innerHTML = '<i class="fas fa-exclamation-triangle me-1"></i>Error';
|
||||
setTimeout(() => {
|
||||
refreshBtn.innerHTML = originalHtml;
|
||||
refreshBtn.disabled = false;
|
||||
}, 2000);
|
||||
}
|
||||
}
|
||||
|
||||
function startProgressMonitoring() {
|
||||
// Find all processing files and start monitoring them
|
||||
const processingCards = document.querySelectorAll('.card');
|
||||
@@ -534,19 +582,19 @@ function startFileProgressMonitoring(fileId) {
|
||||
|
||||
// Stop monitoring if processing is complete
|
||||
if (result.progress.status !== 'processing') {
|
||||
console.log(`File ${fileId} finished processing with status: ${result.progress.status}`);
|
||||
clearInterval(progressMonitoring[fileId]);
|
||||
delete progressMonitoring[fileId];
|
||||
|
||||
// Refresh page to show final status
|
||||
setTimeout(() => {
|
||||
location.reload();
|
||||
}, 2000);
|
||||
// Reload page immediately to show final status
|
||||
console.log('Reloading page to show updated status...');
|
||||
location.reload();
|
||||
}
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('Error checking progress:', error);
|
||||
}
|
||||
}, 2000); // Check every 2 seconds
|
||||
}, 1000); // Check every 1 second for faster updates
|
||||
}
|
||||
|
||||
function updateProgressDisplay(fileId, progress) {
|
||||
@@ -631,7 +679,7 @@ function stopAllProgressMonitoring() {
|
||||
// Clean up when page unloads
|
||||
window.addEventListener('beforeunload', stopAllProgressMonitoring);
|
||||
|
||||
// Auto-refresh processing status every 10 seconds for files that are still processing
|
||||
// Auto-refresh processing status for files that are still processing
|
||||
document.addEventListener('DOMContentLoaded', function() {
|
||||
// Start progress monitoring for processing files
|
||||
startProgressMonitoring();
|
||||
@@ -648,8 +696,31 @@ document.addEventListener('DOMContentLoaded', function() {
|
||||
|
||||
if (hasProcessingFiles) {
|
||||
console.log('Found processing files, setting up auto-refresh...');
|
||||
setInterval(() => {
|
||||
// Check again if there are still processing files
|
||||
|
||||
// More frequent checking - every 3 seconds
|
||||
const statusCheckInterval = setInterval(async () => {
|
||||
console.log('Checking file statuses...');
|
||||
|
||||
try {
|
||||
const response = await fetch('/api/files/status/all');
|
||||
const result = await response.json();
|
||||
|
||||
if (result.success) {
|
||||
console.log('Status check result:', result.summary);
|
||||
|
||||
// If no more processing files, reload page to show final status
|
||||
if (result.summary.processing === 0) {
|
||||
console.log('No more processing files, reloading page...');
|
||||
clearInterval(statusCheckInterval);
|
||||
location.reload();
|
||||
return;
|
||||
}
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('Error in status check:', error);
|
||||
}
|
||||
|
||||
// Also check DOM for processing badges
|
||||
const currentBadges = document.querySelectorAll('.badge');
|
||||
let stillProcessing = false;
|
||||
|
||||
@@ -659,11 +730,22 @@ document.addEventListener('DOMContentLoaded', function() {
|
||||
}
|
||||
});
|
||||
|
||||
if (stillProcessing) {
|
||||
console.log('Still have processing files, refreshing page...');
|
||||
if (!stillProcessing) {
|
||||
console.log('No processing badges found, reloading page...');
|
||||
clearInterval(statusCheckInterval);
|
||||
location.reload();
|
||||
}
|
||||
}, 10000); // Check every 10 seconds
|
||||
}, 3000); // Check every 3 seconds
|
||||
|
||||
// Also add a manual refresh reminder
|
||||
setTimeout(() => {
|
||||
const processingBadges = Array.from(document.querySelectorAll('.badge')).filter(badge =>
|
||||
badge.textContent && badge.textContent.includes('Processing')
|
||||
);
|
||||
if (processingBadges.length > 0) {
|
||||
console.log('Files still processing after 10 seconds, you can click refresh manually');
|
||||
}
|
||||
}, 10000);
|
||||
}
|
||||
});
|
||||
</script>
|
||||
|
||||
Reference in New Issue
Block a user