Chatbot / templates /admin.html
HARI KRISHNA
initial
ec1988c
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Admin Dashboard - SASTRA Chatbot</title>
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0-alpha1/dist/css/bootstrap.min.css" rel="stylesheet">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.0.0/css/all.min.css">
<link rel="stylesheet" href="{{ url_for('static', filename='css/style.css') }}">
</head>
<body>
<!-- Admin Header -->
<nav class="navbar navbar-expand-lg navbar-dark bg-dark">
<div class="container">
<a class="navbar-brand" href="/">
<i class="fas fa-university me-2"></i>SASTRA Admin
</a>
<div class="navbar-nav ms-auto">
<a href="/" class="nav-link">
<i class="fas fa-robot me-1"></i>Chat
</a>
<a href="/logout" class="nav-link">
<i class="fas fa-sign-out-alt me-1"></i>Logout
</a>
</div>
</div>
</nav>
<div class="container mt-4">
<div class="row">
<div class="col-md-12">
<h2 class="mb-4">
<i class="fas fa-tachometer-alt me-2"></i>Admin Dashboard
</h2>
</div>
</div>
<!-- Retraining Section -->
<div class="row mb-4">
<div class="col-md-12">
<div class="card">
<div class="card-header bg-warning text-dark">
<h5 class="mb-0">
<i class="fas fa-retweet me-2"></i>Model Retraining
</h5>
</div>
<div class="card-body">
<div class="alert alert-info">
<i class="fas fa-info-circle me-2"></i>
Upload a new Excel file with keyword-response pairs to update the chatbot's knowledge.
</div>
<form id="retrainForm">
<div class="mb-3">
<label for="trainingFile" class="form-label">Upload Training Data (Excel)</label>
<input class="form-control" type="file" id="trainingFile" accept=".xlsx">
<div class="form-text">
Excel file should have columns: "keyword" and "response"
</div>
</div>
<div class="d-flex gap-2">
<button type="submit" class="btn btn-warning" id="retrainBtn">
<i class="fas fa-sync me-2"></i>Retrain Model
</button>
<a href="/api/download_logs" class="btn btn-outline-primary">
<i class="fas fa-download me-2"></i>Download Logs
</a>
</div>
</form>
<div id="retrainResult" class="mt-3"></div>
</div>
</div>
</div>
</div>
<!-- Analytics Section -->
<div class="row">
<div class="col-md-12">
<div class="card">
<div class="card-header bg-success text-white">
<h5 class="mb-0">
<i class="fas fa-chart-bar me-2"></i>Analytics Dashboard
</h5>
</div>
<div class="card-body">
<div class="d-flex justify-content-between mb-3">
<button class="btn btn-outline-success" onclick="refreshAnalytics()">
<i class="fas fa-redo me-2"></i>Refresh Analytics
</button>
<span class="text-muted">Last updated: <span id="lastUpdate">Never</span></span>
</div>
<!-- Analytics Cards -->
<div class="row" id="analyticsCards">
<div class="col-md-3 mb-3">
<div class="card text-center h-100">
<div class="card-body">
<h1 class="display-4 text-primary" id="totalQueries">0</h1>
<p class="card-text">Total Queries</p>
</div>
</div>
</div>
<div class="col-md-9 mb-3">
<div class="card h-100">
<div class="card-header">
<h6 class="mb-0">Language Distribution</h6>
</div>
<div class="card-body">
<div class="table-responsive">
<table class="table table-sm" id="langTable">
<tbody>
<!-- Filled by JavaScript -->
</tbody>
</table>
</div>
</div>
</div>
</div>
</div>
<!-- Response Types & Top Questions -->
<div class="row mt-3">
<div class="col-md-6 mb-3">
<div class="card h-100">
<div class="card-header">
<h6 class="mb-0">Response Types</h6>
</div>
<div class="card-body">
<div class="table-responsive">
<table class="table table-sm" id="responseTypeTable">
<tbody>
<!-- Filled by JavaScript -->
</tbody>
</table>
</div>
</div>
</div>
</div>
<div class="col-md-6 mb-3">
<div class="card h-100">
<div class="card-header">
<h6 class="mb-0">Recent Questions</h6>
</div>
<div class="card-body">
<ul class="list-group list-group-flush" id="topQuestions">
<!-- Filled by JavaScript -->
</ul>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
<!-- Bootstrap JS -->
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0-alpha1/dist/js/bootstrap.bundle.min.js"></script>
<!-- Admin JavaScript -->
<script>
document.getElementById('retrainForm').addEventListener('submit', async function(e) {
e.preventDefault();
const fileInput = document.getElementById('trainingFile');
const retrainBtn = document.getElementById('retrainBtn');
const resultDiv = document.getElementById('retrainResult');
if (!fileInput.files.length) {
resultDiv.innerHTML = `
<div class="alert alert-warning">
<i class="fas fa-exclamation-triangle me-2"></i>
Please select an Excel file to upload.
</div>
`;
return;
}
const formData = new FormData();
formData.append('file', fileInput.files[0]);
retrainBtn.disabled = true;
retrainBtn.innerHTML = '<i class="fas fa-spinner fa-spin me-2"></i>Retraining...';
try {
const response = await fetch('/api/retrain', {
method: 'POST',
body: formData
});
const data = await response.json();
if (response.ok) {
resultDiv.innerHTML = `
<div class="alert alert-success">
<i class="fas fa-check-circle me-2"></i>
${data.message}
</div>
`;
// Refresh analytics after retraining
refreshAnalytics();
} else {
resultDiv.innerHTML = `
<div class="alert alert-danger">
<i class="fas fa-times-circle me-2"></i>
Error: ${data.error || 'Failed to retrain'}
</div>
`;
}
} catch (error) {
resultDiv.innerHTML = `
<div class="alert alert-danger">
<i class="fas fa-times-circle me-2"></i>
Network error: ${error.message}
</div>
`;
} finally {
retrainBtn.disabled = false;
retrainBtn.innerHTML = '<i class="fas fa-sync me-2"></i>Retrain Model';
}
});
async function refreshAnalytics() {
try {
const response = await fetch('/api/analytics');
const data = await response.json();
if (response.ok) {
// Update last update time
const now = new Date();
document.getElementById('lastUpdate').textContent = now.toLocaleTimeString();
// Update total queries
document.getElementById('totalQueries').textContent = data.total_queries || 0;
// Update language distribution
const langTable = document.getElementById('langTable');
langTable.innerHTML = '';
if (data.language_distribution) {
for (const [lang, count] of Object.entries(data.language_distribution)) {
const row = document.createElement('tr');
row.innerHTML = `
<td>${getLanguageName(lang)}</td>
<td>${count}</td>
<td>
<div class="progress" style="height: 10px;">
<div class="progress-bar" style="width: ${(count / data.total_queries * 100) || 0}%"></div>
</div>
</td>
`;
langTable.appendChild(row);
}
}
// Update response types
const responseTable = document.getElementById('responseTypeTable');
responseTable.innerHTML = '';
if (data.response_types) {
for (const [type, count] of Object.entries(data.response_types)) {
const row = document.createElement('tr');
const badgeColor = getResponseTypeColor(type);
row.innerHTML = `
<td><span class="badge ${badgeColor}">${type.toUpperCase()}</span></td>
<td>${count}</td>
`;
responseTable.appendChild(row);
}
}
// Update top questions
const topQuestions = document.getElementById('topQuestions');
topQuestions.innerHTML = '';
if (data.top_questions && data.top_questions.length > 0) {
data.top_questions.forEach(question => {
const li = document.createElement('li');
li.className = 'list-group-item';
li.textContent = question.length > 50 ? question.substring(0, 50) + '...' : question;
topQuestions.appendChild(li);
});
}
}
} catch (error) {
console.error('Error refreshing analytics:', error);
}
}
function getLanguageName(code) {
const languages = {
'en': 'English',
'ta': 'Tamil',
'te': 'Telugu',
'kn': 'Kannada',
'hi': 'Hindi',
'unknown': 'Unknown'
};
return languages[code] || code;
}
function getResponseTypeColor(type) {
const colors = {
'keyword': 'bg-warning',
'rag': 'bg-info',
'llm': 'bg-primary',
'error': 'bg-danger'
};
return colors[type] || 'bg-secondary';
}
// Load analytics on page load
document.addEventListener('DOMContentLoaded', refreshAnalytics);
</script>
</body>
</html>