Fix upload 'processing' status
This commit is contained in:
182
server.js
182
server.js
@@ -634,7 +634,7 @@ app.post('/upload', requireAuth, upload.single('noteFile'), async (req, res) =>
|
|||||||
console.log('Response sent, starting async processing...');
|
console.log('Response sent, starting async processing...');
|
||||||
|
|
||||||
// Process document asynchronously
|
// Process document asynchronously
|
||||||
processDocumentAsync(fileInfo, req.session.userId);
|
processDocumentAsync(fileInfo, req.session.userId, req.session);
|
||||||
|
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('Upload error:', error);
|
console.error('Upload error:', error);
|
||||||
@@ -647,13 +647,24 @@ app.post('/upload', requireAuth, upload.single('noteFile'), async (req, res) =>
|
|||||||
});
|
});
|
||||||
|
|
||||||
// Async function to process document and upsert to Flowise using FormData
|
// Async function to process document and upsert to Flowise using FormData
|
||||||
async function processDocumentAsync(fileInfo, userId) {
|
async function processDocumentAsync(fileInfo, userId, session) {
|
||||||
try {
|
try {
|
||||||
console.log('=== DOCUMENT PROCESSING START (FormData) ===');
|
console.log('=== DOCUMENT PROCESSING START (FormData) ===');
|
||||||
console.log(`Starting document processing for: ${fileInfo.originalName}`);
|
console.log(`Starting document processing for: ${fileInfo.originalName}`);
|
||||||
console.log(`File path: ${fileInfo.path}`);
|
console.log(`File path: ${fileInfo.path}`);
|
||||||
console.log(`File size: ${fileInfo.size} bytes`);
|
console.log(`File size: ${fileInfo.size} bytes`);
|
||||||
console.log(`User ID: ${userId}`);
|
console.log(`User ID: ${userId}`);
|
||||||
|
console.log(`Session ID in processing: ${session.id || 'undefined'}`);
|
||||||
|
|
||||||
|
// Find the file in the session to update it by reference
|
||||||
|
const sessionFile = session.uploadedFiles.find(f => f.id === fileInfo.id);
|
||||||
|
if (!sessionFile) {
|
||||||
|
console.error('File not found in session:', fileInfo.id);
|
||||||
|
console.error('Available files in session:', session.uploadedFiles.map(f => ({ id: f.id, name: f.originalName })));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
console.log('Found session file for update:', { id: sessionFile.id, name: sessionFile.originalName, currentStatus: sessionFile.status });
|
||||||
|
|
||||||
// Create document metadata
|
// Create document metadata
|
||||||
const documentMetadata = {
|
const documentMetadata = {
|
||||||
@@ -668,7 +679,7 @@ async function processDocumentAsync(fileInfo, userId) {
|
|||||||
console.log('Document metadata:', documentMetadata);
|
console.log('Document metadata:', documentMetadata);
|
||||||
|
|
||||||
// Initialize processing result
|
// Initialize processing result
|
||||||
fileInfo.processingResult = {
|
sessionFile.processingResult = {
|
||||||
totalChunks: 1, // FormData uploads are single operations
|
totalChunks: 1, // FormData uploads are single operations
|
||||||
successfulChunks: 0,
|
successfulChunks: 0,
|
||||||
failedChunks: 0,
|
failedChunks: 0,
|
||||||
@@ -683,41 +694,71 @@ async function processDocumentAsync(fileInfo, userId) {
|
|||||||
|
|
||||||
console.log('FormData upsert result:', upsertResult);
|
console.log('FormData upsert result:', upsertResult);
|
||||||
|
|
||||||
// Update file info with processing results
|
// Update session file with processing results
|
||||||
fileInfo.status = upsertResult.success ? 'processed' : 'failed';
|
sessionFile.status = upsertResult.success ? 'processed' : 'failed';
|
||||||
fileInfo.processingProgress = null; // Clear progress when done
|
sessionFile.processingProgress = null; // Clear progress when done
|
||||||
fileInfo.processingResult = {
|
sessionFile.processingResult = {
|
||||||
totalChunks: upsertResult.totalChunks,
|
totalChunks: upsertResult.totalChunks,
|
||||||
successfulChunks: upsertResult.successfulChunks,
|
successfulChunks: upsertResult.successfulChunks,
|
||||||
failedChunks: upsertResult.failedChunks,
|
failedChunks: upsertResult.failedChunks,
|
||||||
processedAt: new Date().toISOString(),
|
processedAt: new Date().toISOString(),
|
||||||
startedAt: fileInfo.processingResult.startedAt,
|
startedAt: sessionFile.processingResult.startedAt,
|
||||||
duration: Date.now() - new Date(fileInfo.processingResult.startedAt).getTime(),
|
duration: Date.now() - new Date(sessionFile.processingResult.startedAt).getTime(),
|
||||||
method: 'formdata'
|
method: 'formdata'
|
||||||
};
|
};
|
||||||
|
|
||||||
if (upsertResult.errors.length > 0) {
|
if (upsertResult.errors.length > 0) {
|
||||||
fileInfo.processingErrors = upsertResult.errors;
|
sessionFile.processingErrors = upsertResult.errors;
|
||||||
console.log(`Processing errors for ${fileInfo.originalName}:`, upsertResult.errors);
|
console.log(`Processing errors for ${sessionFile.originalName}:`, upsertResult.errors);
|
||||||
}
|
}
|
||||||
|
|
||||||
console.log(`Document processing completed for: ${fileInfo.originalName}`);
|
console.log(`Document processing completed for: ${sessionFile.originalName}`);
|
||||||
console.log(`Result: FormData upload ${upsertResult.success ? 'successful' : 'failed'}`);
|
console.log(`Result: FormData upload ${upsertResult.success ? 'successful' : 'failed'}`);
|
||||||
|
console.log(`Updated session file status to: ${sessionFile.status}`);
|
||||||
|
|
||||||
|
// Verify the session file was updated
|
||||||
|
console.log('Session file after update:', { id: sessionFile.id, name: sessionFile.originalName, status: sessionFile.status });
|
||||||
|
console.log('All session files after update:', session.uploadedFiles.map(f => ({ id: f.id, name: f.originalName, status: f.status })));
|
||||||
|
|
||||||
|
// Force session save since we modified it in an async context
|
||||||
|
session.save((err) => {
|
||||||
|
if (err) {
|
||||||
|
console.error('Error saving session after document processing:', err);
|
||||||
|
} else {
|
||||||
|
console.log('Session saved successfully after document processing');
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
// Log final upsert verification
|
// Log final upsert verification
|
||||||
console.log('Final FormData upsert verification:', {
|
console.log('Final FormData upsert verification:', {
|
||||||
documentStore: `${FLOWISE_BASE_URL}/api/v1/document-store/${FLOWISE_DOCUMENT_STORE_ID}`,
|
documentStore: `${FLOWISE_BASE_URL}/api/v1/document-store/${FLOWISE_DOCUMENT_STORE_ID}`,
|
||||||
documentId: fileInfo.id,
|
documentId: sessionFile.id,
|
||||||
fileName: fileInfo.originalName,
|
fileName: sessionFile.originalName,
|
||||||
success: upsertResult.success
|
success: upsertResult.success,
|
||||||
|
finalStatus: sessionFile.status
|
||||||
});
|
});
|
||||||
|
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error(`Error processing document ${fileInfo.originalName}:`, error);
|
console.error(`Error processing document ${fileInfo.originalName}:`, error);
|
||||||
fileInfo.status = 'failed';
|
|
||||||
fileInfo.processingError = error.message;
|
// Find the file in the session to update it with error
|
||||||
fileInfo.processingResult = fileInfo.processingResult || {};
|
const sessionFile = session.uploadedFiles.find(f => f.id === fileInfo.id);
|
||||||
fileInfo.processingResult.failedAt = new Date().toISOString();
|
if (sessionFile) {
|
||||||
|
sessionFile.status = 'failed';
|
||||||
|
sessionFile.processingError = error.message;
|
||||||
|
sessionFile.processingResult = sessionFile.processingResult || {};
|
||||||
|
sessionFile.processingResult.failedAt = new Date().toISOString();
|
||||||
|
console.log(`Updated session file status to: ${sessionFile.status} due to error`);
|
||||||
|
|
||||||
|
// Force session save since we modified it in an async context
|
||||||
|
session.save((err) => {
|
||||||
|
if (err) {
|
||||||
|
console.error('Error saving session after processing error:', err);
|
||||||
|
} else {
|
||||||
|
console.log('Session saved successfully after processing error');
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -806,34 +847,115 @@ app.post('/api/revise', requireAuth, async (req, res) => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
app.get('/chat', requireAuth, (req, res) => {
|
app.get('/chat', requireAuth, (req, res) => {
|
||||||
|
// Initialize chat history if it doesn't exist
|
||||||
|
if (!req.session.chatHistory) {
|
||||||
|
req.session.chatHistory = [];
|
||||||
|
}
|
||||||
|
|
||||||
res.render('chat', {
|
res.render('chat', {
|
||||||
title: 'Chat with EduCat AI'
|
title: 'Chat with EduCat AI',
|
||||||
|
chatHistory: req.session.chatHistory
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
app.post('/api/chat', requireAuth, async (req, res) => {
|
app.post('/api/chat', requireAuth, async (req, res) => {
|
||||||
try {
|
try {
|
||||||
const { message, history } = req.body;
|
const { message } = req.body;
|
||||||
|
|
||||||
// Call Flowise API for chat
|
// Initialize chat history in session if it doesn't exist
|
||||||
|
if (!req.session.chatHistory) {
|
||||||
|
req.session.chatHistory = [];
|
||||||
|
}
|
||||||
|
|
||||||
|
console.log('Chat message received:', message);
|
||||||
|
console.log('Current chat history length:', req.session.chatHistory.length);
|
||||||
|
|
||||||
|
// Call Flowise API for chat with session history
|
||||||
const response = await axios.post(`${FLOWISE_API_URL}/${FLOWISE_CHATFLOW_ID}`, {
|
const response = await axios.post(`${FLOWISE_API_URL}/${FLOWISE_CHATFLOW_ID}`, {
|
||||||
question: message,
|
question: message,
|
||||||
history: history || []
|
history: req.session.chatHistory
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const aiResponse = response.data.text || response.data.answer || 'No response received';
|
||||||
|
|
||||||
|
// Add the conversation to session history
|
||||||
|
req.session.chatHistory.push({
|
||||||
|
human: message,
|
||||||
|
ai: aiResponse
|
||||||
|
});
|
||||||
|
|
||||||
|
// Save session explicitly since we modified it
|
||||||
|
req.session.save((err) => {
|
||||||
|
if (err) {
|
||||||
|
console.error('Error saving chat session:', err);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
console.log('Updated chat history length:', req.session.chatHistory.length);
|
||||||
|
|
||||||
res.json({
|
res.json({
|
||||||
success: true,
|
success: true,
|
||||||
response: response.data.text || response.data.answer || 'No response received'
|
response: aiResponse
|
||||||
});
|
});
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('Chat error:', error);
|
console.error('Chat error:', error);
|
||||||
res.status(500).json({
|
res.status(500).json({
|
||||||
|
success: false,
|
||||||
error: 'Failed to get chat response',
|
error: 'Failed to get chat response',
|
||||||
details: error.message
|
details: error.message
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// Get chat history from session
|
||||||
|
app.get('/api/chat/history', requireAuth, (req, res) => {
|
||||||
|
try {
|
||||||
|
const chatHistory = req.session.chatHistory || [];
|
||||||
|
console.log('Chat history requested, returning', chatHistory.length, 'messages');
|
||||||
|
|
||||||
|
res.json({
|
||||||
|
success: true,
|
||||||
|
history: chatHistory
|
||||||
|
});
|
||||||
|
} catch (error) {
|
||||||
|
console.error('Error getting chat history:', error);
|
||||||
|
res.status(500).json({
|
||||||
|
success: false,
|
||||||
|
error: 'Failed to get chat history',
|
||||||
|
details: error.message
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// Clear chat history
|
||||||
|
app.delete('/api/chat/history', requireAuth, (req, res) => {
|
||||||
|
try {
|
||||||
|
req.session.chatHistory = [];
|
||||||
|
req.session.save((err) => {
|
||||||
|
if (err) {
|
||||||
|
console.error('Error clearing chat session:', err);
|
||||||
|
return res.status(500).json({
|
||||||
|
success: false,
|
||||||
|
error: 'Failed to clear chat history'
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
console.log('Chat history cleared for user:', req.session.userId);
|
||||||
|
res.json({
|
||||||
|
success: true,
|
||||||
|
message: 'Chat history cleared'
|
||||||
|
});
|
||||||
|
});
|
||||||
|
} catch (error) {
|
||||||
|
console.error('Error clearing chat history:', error);
|
||||||
|
res.status(500).json({
|
||||||
|
success: false,
|
||||||
|
error: 'Failed to clear chat history',
|
||||||
|
details: error.message
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
app.get('/dashboard', requireAuth, (req, res) => {
|
app.get('/dashboard', requireAuth, (req, res) => {
|
||||||
const files = req.session.uploadedFiles || [];
|
const files = req.session.uploadedFiles || [];
|
||||||
res.render('dashboard', {
|
res.render('dashboard', {
|
||||||
@@ -921,6 +1043,12 @@ app.get('/api/files/:fileId/status', requireAuth, async (req, res) => {
|
|||||||
const files = req.session.uploadedFiles || [];
|
const files = req.session.uploadedFiles || [];
|
||||||
const file = files.find(f => f.id === fileId);
|
const file = files.find(f => f.id === fileId);
|
||||||
|
|
||||||
|
console.log(`Status requested for file ${fileId}`);
|
||||||
|
console.log(`Session ID: ${req.session.id || req.sessionID}`);
|
||||||
|
console.log(`User ID: ${req.session.userId}`);
|
||||||
|
console.log(`Files in session:`, files.map(f => ({ id: f.id, name: f.originalName, status: f.status })));
|
||||||
|
console.log(`Found file:`, file ? { id: file.id, name: file.originalName, status: file.status } : 'Not found');
|
||||||
|
|
||||||
if (!file) {
|
if (!file) {
|
||||||
return res.status(404).json({ success: false, error: 'File not found' });
|
return res.status(404).json({ success: false, error: 'File not found' });
|
||||||
}
|
}
|
||||||
@@ -969,7 +1097,7 @@ app.post('/api/files/:fileId/retry', requireAuth, async (req, res) => {
|
|||||||
file.processingErrors = null;
|
file.processingErrors = null;
|
||||||
|
|
||||||
// Start processing asynchronously
|
// Start processing asynchronously
|
||||||
processDocumentAsync(file, req.session.userId);
|
processDocumentAsync(file, req.session.userId, req.session);
|
||||||
|
|
||||||
res.json({
|
res.json({
|
||||||
success: true,
|
success: true,
|
||||||
@@ -989,6 +1117,8 @@ app.post('/api/files/:fileId/retry', requireAuth, async (req, res) => {
|
|||||||
app.get('/api/files/status/all', requireAuth, async (req, res) => {
|
app.get('/api/files/status/all', requireAuth, async (req, res) => {
|
||||||
try {
|
try {
|
||||||
const files = req.session.uploadedFiles || [];
|
const files = req.session.uploadedFiles || [];
|
||||||
|
console.log('Status check requested for session files:', files.map(f => ({ id: f.id, name: f.originalName, status: f.status })));
|
||||||
|
|
||||||
const statusSummary = files.map(file => ({
|
const statusSummary = files.map(file => ({
|
||||||
id: file.id,
|
id: file.id,
|
||||||
originalName: file.originalName,
|
originalName: file.originalName,
|
||||||
@@ -1010,6 +1140,8 @@ app.get('/api/files/status/all', requireAuth, async (req, res) => {
|
|||||||
files: statusSummary
|
files: statusSummary
|
||||||
};
|
};
|
||||||
|
|
||||||
|
console.log('Returning status summary:', summary);
|
||||||
|
|
||||||
res.json({
|
res.json({
|
||||||
success: true,
|
success: true,
|
||||||
summary: summary
|
summary: summary
|
||||||
|
|||||||
104
views/chat.ejs
104
views/chat.ejs
@@ -5,23 +5,16 @@
|
|||||||
<div class="col-lg-8">
|
<div class="col-lg-8">
|
||||||
<div class="card shadow-lg border-0 chat">
|
<div class="card shadow-lg border-0 chat">
|
||||||
<div class="card-header bg-primary text-white">
|
<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>
|
||||||
<div class="card-body p-0">
|
<div class="card-body p-0">
|
||||||
<div id="chat-container" class="p-4" style="height: 500px; overflow-y: auto;">
|
<div id="chat-container" class="p-4" style="height: 500px; overflow-y: auto;">
|
||||||
<div class="chat-message bot-message mb-3">
|
<!-- Initial bot message will be added here if no history exists -->
|
||||||
<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>
|
|
||||||
</div>
|
</div>
|
||||||
<div class="border-top bg-light p-3">
|
<div class="border-top bg-light p-3">
|
||||||
<div class="input-group">
|
<div class="input-group">
|
||||||
@@ -59,12 +52,17 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
let chatHistory = [];
|
// Get chat history from server-side rendered data
|
||||||
|
const serverChatHistory = <%- JSON.stringify(chatHistory || []) %>;
|
||||||
|
|
||||||
document.addEventListener('DOMContentLoaded', function() {
|
document.addEventListener('DOMContentLoaded', function() {
|
||||||
const chatContainer = document.getElementById('chat-container');
|
const chatContainer = document.getElementById('chat-container');
|
||||||
const chatInput = document.getElementById('chat-input');
|
const chatInput = document.getElementById('chat-input');
|
||||||
const sendBtn = document.getElementById('send-btn');
|
const sendBtn = document.getElementById('send-btn');
|
||||||
|
const clearChatBtn = document.getElementById('clear-chat-btn');
|
||||||
|
|
||||||
|
// Load existing chat history from server
|
||||||
|
loadChatHistory();
|
||||||
|
|
||||||
sendBtn.addEventListener('click', sendMessage);
|
sendBtn.addEventListener('click', sendMessage);
|
||||||
chatInput.addEventListener('keypress', function(e) {
|
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() {
|
function sendMessage() {
|
||||||
const message = chatInput.value.trim();
|
const message = chatInput.value.trim();
|
||||||
if (!message) return;
|
if (!message) return;
|
||||||
@@ -88,8 +125,7 @@ document.addEventListener('DOMContentLoaded', function() {
|
|||||||
sendToAI(message);
|
sendToAI(message);
|
||||||
}
|
}
|
||||||
|
|
||||||
function addMessageToChat(sender, message) {
|
function addMessageToChat(sender, message, withScroll = true) {
|
||||||
const chatContainer = document.getElementById('chat-container');
|
|
||||||
const messageDiv = document.createElement('div');
|
const messageDiv = document.createElement('div');
|
||||||
messageDiv.className = `chat-message ${sender}-message mb-3`;
|
messageDiv.className = `chat-message ${sender}-message mb-3`;
|
||||||
|
|
||||||
@@ -126,11 +162,12 @@ document.addEventListener('DOMContentLoaded', function() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
chatContainer.appendChild(messageDiv);
|
chatContainer.appendChild(messageDiv);
|
||||||
chatContainer.scrollTop = chatContainer.scrollHeight;
|
if (withScroll) {
|
||||||
|
chatContainer.scrollTop = chatContainer.scrollHeight;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function addTypingIndicator() {
|
function addTypingIndicator() {
|
||||||
const chatContainer = document.getElementById('chat-container');
|
|
||||||
const typingDiv = document.createElement('div');
|
const typingDiv = document.createElement('div');
|
||||||
typingDiv.id = 'typing-indicator';
|
typingDiv.id = 'typing-indicator';
|
||||||
typingDiv.className = 'chat-message bot-message mb-3';
|
typingDiv.className = 'chat-message bot-message mb-3';
|
||||||
@@ -170,8 +207,7 @@ document.addEventListener('DOMContentLoaded', function() {
|
|||||||
'Content-Type': 'application/json',
|
'Content-Type': 'application/json',
|
||||||
},
|
},
|
||||||
body: JSON.stringify({
|
body: JSON.stringify({
|
||||||
message: message,
|
message: message
|
||||||
history: chatHistory
|
|
||||||
})
|
})
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -181,7 +217,6 @@ document.addEventListener('DOMContentLoaded', function() {
|
|||||||
|
|
||||||
if (result.success) {
|
if (result.success) {
|
||||||
addMessageToChat('bot', result.response);
|
addMessageToChat('bot', result.response);
|
||||||
chatHistory.push({human: message, ai: result.response});
|
|
||||||
} else {
|
} else {
|
||||||
addMessageToChat('bot', 'Sorry, I encountered an error. Please try again.');
|
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.');
|
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>
|
</script>
|
||||||
|
|
||||||
|
|||||||
@@ -5,9 +5,14 @@
|
|||||||
<div class="col-12">
|
<div class="col-12">
|
||||||
<div class="d-flex justify-content-between align-items-center mb-4">
|
<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>
|
<h2><i class="fas fa-tachometer-alt me-2"></i>Your Dashboard</h2>
|
||||||
<a href="/upload" class="btn btn-primary">
|
<div>
|
||||||
<i class="fas fa-plus me-2"></i>Upload New Notes
|
<button class="btn btn-outline-secondary me-2" onclick="refreshStatus()" id="refreshBtn">
|
||||||
</a>
|
<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>
|
</div>
|
||||||
|
|
||||||
<% if (files.length === 0) { %>
|
<% if (files.length === 0) { %>
|
||||||
@@ -497,6 +502,49 @@ async function viewProcessingDetails(fileId) {
|
|||||||
// Progress monitoring for processing files
|
// Progress monitoring for processing files
|
||||||
let progressMonitoring = {};
|
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() {
|
function startProgressMonitoring() {
|
||||||
// Find all processing files and start monitoring them
|
// Find all processing files and start monitoring them
|
||||||
const processingCards = document.querySelectorAll('.card');
|
const processingCards = document.querySelectorAll('.card');
|
||||||
@@ -534,19 +582,19 @@ function startFileProgressMonitoring(fileId) {
|
|||||||
|
|
||||||
// Stop monitoring if processing is complete
|
// Stop monitoring if processing is complete
|
||||||
if (result.progress.status !== 'processing') {
|
if (result.progress.status !== 'processing') {
|
||||||
|
console.log(`File ${fileId} finished processing with status: ${result.progress.status}`);
|
||||||
clearInterval(progressMonitoring[fileId]);
|
clearInterval(progressMonitoring[fileId]);
|
||||||
delete progressMonitoring[fileId];
|
delete progressMonitoring[fileId];
|
||||||
|
|
||||||
// Refresh page to show final status
|
// Reload page immediately to show final status
|
||||||
setTimeout(() => {
|
console.log('Reloading page to show updated status...');
|
||||||
location.reload();
|
location.reload();
|
||||||
}, 2000);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('Error checking progress:', error);
|
console.error('Error checking progress:', error);
|
||||||
}
|
}
|
||||||
}, 2000); // Check every 2 seconds
|
}, 1000); // Check every 1 second for faster updates
|
||||||
}
|
}
|
||||||
|
|
||||||
function updateProgressDisplay(fileId, progress) {
|
function updateProgressDisplay(fileId, progress) {
|
||||||
@@ -631,7 +679,7 @@ function stopAllProgressMonitoring() {
|
|||||||
// Clean up when page unloads
|
// Clean up when page unloads
|
||||||
window.addEventListener('beforeunload', stopAllProgressMonitoring);
|
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() {
|
document.addEventListener('DOMContentLoaded', function() {
|
||||||
// Start progress monitoring for processing files
|
// Start progress monitoring for processing files
|
||||||
startProgressMonitoring();
|
startProgressMonitoring();
|
||||||
@@ -648,8 +696,31 @@ document.addEventListener('DOMContentLoaded', function() {
|
|||||||
|
|
||||||
if (hasProcessingFiles) {
|
if (hasProcessingFiles) {
|
||||||
console.log('Found processing files, setting up auto-refresh...');
|
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');
|
const currentBadges = document.querySelectorAll('.badge');
|
||||||
let stillProcessing = false;
|
let stillProcessing = false;
|
||||||
|
|
||||||
@@ -659,11 +730,22 @@ document.addEventListener('DOMContentLoaded', function() {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
if (stillProcessing) {
|
if (!stillProcessing) {
|
||||||
console.log('Still have processing files, refreshing page...');
|
console.log('No processing badges found, reloading page...');
|
||||||
|
clearInterval(statusCheckInterval);
|
||||||
location.reload();
|
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>
|
</script>
|
||||||
|
|||||||
Reference in New Issue
Block a user