From 3d0818cec4b51b29a79a5473e953ab7f79fd0cce Mon Sep 17 00:00:00 2001 From: Muhammad Bin Khalid Date: Tue, 3 Jun 2025 02:20:56 +0500 Subject: [PATCH 1/3] Refactor database queries and update view engine settings; enhance chatbot UI with pagination and loading indicators --- index.js | 8 +- routes/main.js | 18 +- views/mainPages/chatbot.handlebars | 532 ++++++++++++++++++++++++----- 3 files changed, 470 insertions(+), 88 deletions(-) diff --git a/index.js b/index.js index cda5f8f..6c4b0e8 100644 --- a/index.js +++ b/index.js @@ -38,6 +38,7 @@ router.use( // Configure Handlebars router.engine("handlebars", engine({ partialsDir: [ + path.join(__dirname, "node_modules/mbkauthe/views"), path.join(__dirname, "views/templates"), path.join(__dirname, "views/notice"), path.join(__dirname, "views") @@ -123,7 +124,10 @@ Handlebars.registerHelper('divide', function (value, divisor, multiplier) { }); router.set("view engine", "handlebars"); -router.set("views", path.join(__dirname, "views")); +router.set("views", [ + path.join(__dirname, "views"), + path.join(__dirname, "node_modules/mbkauthe/views") +]); // Serve static files router.use( @@ -177,7 +181,7 @@ router.get('/simulate-error', (req, res, next) => { router.use((req, res) => { console.log(`Path not found: ${req.url}`); - return res.render("staticPage/404"); + return res.render("staticPage/404", { layout: false }); }); router.use((err, req, res, next) => { diff --git a/routes/main.js b/routes/main.js index 33b2265..b046d2b 100644 --- a/routes/main.js +++ b/routes/main.js @@ -68,7 +68,7 @@ const db = { fetchChatHistories: async (username) => { try { const { rows } = await pool.query( - 'SELECT id, created_at, temperature FROM Ai_history WHERE username = $1 ORDER BY created_at DESC', + 'SELECT id, created_at, temperature FROM ai_history_chatapi WHERE username = $1 ORDER BY created_at DESC', [username] ); @@ -158,7 +158,7 @@ const db = { fetchChatHistoryById: async (chatId) => { try { const { rows } = await pool.query( - 'SELECT id, conversation_history, temperature FROM Ai_history WHERE id = $1', + 'SELECT id, conversation_history, temperature FROM ai_history_chatapi WHERE id = $1', [chatId] ); return rows[0] || null; @@ -172,13 +172,13 @@ const db = { try { if (chatId) { await pool.query( - 'UPDATE Ai_history SET conversation_history = $1, created_at = CURRENT_TIMESTAMP, temperature = $3 WHERE id = $2', + 'UPDATE ai_history_chatapi SET conversation_history = $1, created_at = CURRENT_TIMESTAMP, temperature = $3 WHERE id = $2', [JSON.stringify(history), chatId, temperature] ); return chatId; } else { const { rows } = await pool.query( - 'INSERT INTO Ai_history (conversation_history, username, temperature) VALUES ($1, $2, $3) RETURNING id', + 'INSERT INTO ai_history_chatapi (conversation_history, username, temperature) VALUES ($1, $2, $3) RETURNING id', [JSON.stringify(history), username, temperature] ); return rows[0].id; @@ -194,11 +194,11 @@ const db = { const today = new Date().toISOString().split("T")[0]; const [settingsResult, messageLog] = await Promise.all([ pool.query( - 'SELECT theme, font_size, ai_model, temperature, daily_message_limit FROM user_settings WHERE username = $1', + 'SELECT theme, font_size, ai_model, temperature, daily_message_limit FROM user_settings_chatapi WHERE username = $1', [username] ), pool.query( - 'SELECT message_count FROM user_message_logs WHERE username = $1 AND date = $2', + 'SELECT message_count FROM user_message_logs_chatapi WHERE username = $1 AND date = $2', [username, today] ) ]); @@ -236,7 +236,7 @@ const db = { saveUserSettings: async (username, settings) => { try { await pool.query( - `INSERT INTO user_settings (username, theme, font_size, ai_model, temperature) + `INSERT INTO user_settings_chatapi (username, theme, font_size, ai_model, temperature) VALUES ($1, $2, $3, $4, $5) ON CONFLICT (username) DO UPDATE SET @@ -576,7 +576,7 @@ router.post('/api/chat/delete-message/:chatId', validateSessionAndRole("Any"), a console.log(`Saving updated conversation history for Chat ID: ${chatId}`); await pool.query( - 'UPDATE Ai_history SET conversation_history = $1 WHERE id = $2', + 'UPDATE ai_history_chatapi SET conversation_history = $1 WHERE id = $2', [JSON.stringify(conversationHistory), chatId] ); @@ -671,7 +671,7 @@ router.post('/api/chat/clear-history/:chatId', validateSessionAndRole("Any"), as if (!chatId) return res.status(400).json({ message: "Chat ID is required" }); try { - await pool.query('DELETE FROM Ai_history WHERE id = $1', [chatId]); + await pool.query('DELETE FROM ai_history_chatapi WHERE id = $1', [chatId]); res.json({ status: 200, message: "Chat history deleted", chatId }); } catch (error) { handleApiError(res, error, "deleting chat history"); diff --git a/views/mainPages/chatbot.handlebars b/views/mainPages/chatbot.handlebars index e818fcc..f96a5b5 100644 --- a/views/mainPages/chatbot.handlebars +++ b/views/mainPages/chatbot.handlebars @@ -15,7 +15,6 @@ + + + `; + + if (includeMetadata) { + content += ` +
+

Chat Information

+

Chat ID: ${this.chatData.id}

+

Username: ${this.chatData.username}

+

Created: ${this.chatData.created_at}

+

AI Model: ${this.chatData.ai_model}

+

Temperature: ${this.chatData.temperature}

+
+ `; + } + + content += '
'; + conversation.forEach((message, index) => { + content += `
`; + if (includeMetadata) { + content += `
${message.role.toUpperCase()}
`; + } + message.parts.forEach(part => { + if (part.text) { + content += `

${part.text.replace(/\n/g, '
')}

`; + } + }); + content += '
'; + }); + content += '
'; + filename += '.html'; + break; + } + + // Create and download file + const blob = new Blob([content], { type: 'text/plain' }); + const url = window.URL.createObjectURL(blob); + const a = document.createElement('a'); + a.style.display = 'none'; + a.href = url; + a.download = filename; + document.body.appendChild(a); + a.click(); + window.URL.revokeObjectURL(url); + + this.closeModal('exportModal'); + } + + async deleteChat() { + const deleteBtn = document.getElementById('confirmDelete'); + const originalContent = deleteBtn.innerHTML; + + deleteBtn.innerHTML = ' Deleting...'; + deleteBtn.disabled = true; + + try { + const response = await fetch(`/admin/chats/bulk-delete`, { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + }, + body: JSON.stringify({ + chatIds: [this.chatData.id] + }) + }); + + const result = await response.json(); + + if (result.success) { + alert('Chat deleted successfully'); + window.location.href = '/admin/chats'; + } else { + throw new Error(result.message); + } + } catch (error) { + console.error('Delete failed:', error); + alert('Failed to delete chat. Please try again.'); + } finally { + deleteBtn.innerHTML = originalContent; + deleteBtn.disabled = false; + } + } +} + +// Initialize when DOM is loaded +document.addEventListener('DOMContentLoaded', () => { + new ChatDetailView(); +}); + + + diff --git a/views/admin/chats.handlebars b/views/admin/chats.handlebars index 23aad4e..1eeb827 100644 --- a/views/admin/chats.handlebars +++ b/views/admin/chats.handlebars @@ -1,256 +1,1310 @@ + + +
-

Chat Management

- -
- ← Back to Dashboard - -
-
- + +
+
+
+

+ + Chat Management +

+

Monitor and manage all chat conversations

- -
- + +
+
-
- + +
+
+
+
- -
- - to - +
+
{{pagination.totalCount}}
+
Total Chats
- -
- +
+
+
+
- - - Clear All - +
+
-
+
Avg Messages
+
+
+
+
+ +
+
+
-
+
Unique Users
+
+
+
+
+ +
+
+
0
+
Selected
+
+
-
-
0 chats selected
- -
- - + +
+
+

Search & Filter

+
+
+
+ + +
+ +
+ + +
+ +
+ + +
+ +
+ +
+ + to + +
+
+ +
+ +
+ + +
+
+ +
+ + +
+
+ +
+ + + Reset + +
+
+
+ + +
+

Actions & View

+
+
+ + +
+
+ + +
+
-
-
-
- + +
+
+

Conversations

+
+
-
Chat ID
-
Username
-
Date
-
Model
-
Messages
-
Temperature
-
Preview
-
Actions
+
+ + +
+ + + + + + + + + + + + + + + + {{#each chats}} + + + + + + + + + + + + {{/each}} + +
+ + IDUserDateModelMessagesTemperaturePreviewActions
+ + + #{{this.id}} + + + + {{formatDate this.created_at}} + + {{this.ai_model}} + + {{this.message_count}} + + {{this.temperature}}° + +
+ {{truncate this.first_message_preview 50}} +
+
+
+ + + + + + + +
+
- {{#each chats}} -
-
- + + + + +
+
+ Showing {{add (multiply (subtract pagination.currentPage 1) pagination.pageSize) 1}} to + {{#if (lt (multiply pagination.currentPage pagination.pageSize) pagination.totalCount)}} + {{multiply pagination.currentPage pagination.pageSize}} + {{else}} + {{pagination.totalCount}} + {{/if}} + of {{pagination.totalCount}} chats +
+ +
+
+ + + -