Nyan-Proxy / static /js /admin.js
WasabiDrop's picture
Refactor: Organize codebase with modular structure
62be87c
// Admin panel JavaScript functionality
$(document).ready(function() {
// Setup CSRF token for AJAX requests
$.ajaxSetup({
beforeSend: function(xhr, settings) {
if (!/^(GET|HEAD|OPTIONS|TRACE)$/i.test(settings.type) && !this.crossDomain) {
xhr.setRequestHeader("X-CSRFToken", $('meta[name="csrf-token"]').attr('content'));
}
}
});
// Flash message auto-dismiss
setTimeout(function() {
$('.flash').fadeOut();
}, 5000);
// Confirm delete actions
$('.delete-btn').on('click', function(e) {
if (!confirm('Are you sure you want to delete this item?')) {
e.preventDefault();
}
});
// Auto-refresh dashboard stats
if (window.location.pathname === '/admin' || window.location.pathname === '/admin/') {
setInterval(refreshDashboardStats, 30000); // Refresh every 30 seconds
}
});
function refreshDashboardStats() {
$.get('/admin/api/stats', function(data) {
if (data.total_users !== undefined) {
$('.stat-number').eq(0).text(data.total_users);
$('.stat-number').eq(1).text(data.active_users);
$('.stat-number').eq(2).text(data.disabled_users);
$('.stat-number').eq(3).text(data.usage_stats.total_requests || 0);
}
}).fail(function() {
console.log('Failed to refresh dashboard stats');
});
}
// User management functions
function enableUser(token) {
if (confirm('Are you sure you want to enable this user?')) {
$.post(`/admin/users/${token}/enable`, {})
.done(function(data) {
if (data.success) {
location.reload();
} else {
alert('Error: ' + data.error);
}
})
.fail(function() {
alert('Error: Failed to enable user');
});
}
}
function disableUser(token) {
const reason = prompt('Reason for disabling user:');
if (reason) {
$.post(`/admin/users/${token}/disable`, {
reason: reason
})
.done(function(data) {
if (data.success) {
location.reload();
} else {
alert('Error: ' + data.error);
}
})
.fail(function() {
alert('Error: Failed to disable user');
});
}
}
function deleteUser(token) {
if (confirm('Are you sure you want to delete this user? This action cannot be undone.')) {
$.ajax({
url: `/admin/users/${token}`,
type: 'DELETE'
})
.done(function(data) {
if (data.success) {
location.reload();
} else {
alert('Error: ' + data.error);
}
})
.fail(function() {
alert('Error: Failed to delete user');
});
}
}
function rotateUserToken(token) {
if (confirm('Are you sure you want to rotate this user\'s token? The old token will be invalidated.')) {
$.post(`/admin/users/${token}/rotate`, {})
.done(function(data) {
if (data.success) {
alert('Token rotated successfully. New token: ' + data.new_token);
location.reload();
} else {
alert('Error: ' + data.error);
}
})
.fail(function() {
alert('Error: Failed to rotate token');
});
}
}
// Bulk operations
function bulkRefreshQuotas() {
if (confirm('Are you sure you want to refresh quotas for all users?')) {
$.post('/admin/bulk/refresh-quotas', {})
.done(function(data) {
if (data.success) {
alert(`Successfully refreshed quotas for ${data.affected_users} users`);
location.reload();
} else {
alert('Error: ' + data.error);
}
})
.fail(function() {
alert('Error: Failed to refresh quotas');
});
}
}
// Copy to clipboard functionality
function copyToClipboard(text) {
navigator.clipboard.writeText(text).then(function() {
// Show temporary success message
const msg = $('<div class="copy-success">Copied to clipboard!</div>');
$('body').append(msg);
setTimeout(function() {
msg.fadeOut(function() { msg.remove(); });
}, 2000);
}).catch(function(err) {
console.error('Failed to copy to clipboard:', err);
alert('Failed to copy to clipboard');
});
}
// Form validation
function validateUserForm() {
const nickname = $('#nickname').val().trim();
const openaiLimit = $('#openai_limit').val();
const anthropicLimit = $('#anthropic_limit').val();
if (!nickname) {
alert('Please enter a nickname');
return false;
}
if (openaiLimit && (isNaN(openaiLimit) || parseInt(openaiLimit) < 0)) {
alert('OpenAI limit must be a positive number');
return false;
}
if (anthropicLimit && (isNaN(anthropicLimit) || parseInt(anthropicLimit) < 0)) {
alert('Anthropic limit must be a positive number');
return false;
}
return true;
}
// Table sorting
function sortTable(columnIndex) {
const table = document.querySelector('.users-table table');
const tbody = table.querySelector('tbody');
const rows = Array.from(tbody.querySelectorAll('tr'));
rows.sort((a, b) => {
const aText = a.cells[columnIndex].textContent.trim();
const bText = b.cells[columnIndex].textContent.trim();
// Try to parse as numbers first
const aNum = parseFloat(aText);
const bNum = parseFloat(bText);
if (!isNaN(aNum) && !isNaN(bNum)) {
return aNum - bNum;
}
// Otherwise, sort as strings
return aText.localeCompare(bText);
});
tbody.innerHTML = '';
rows.forEach(row => tbody.appendChild(row));
}
// Search functionality
function filterUsers() {
const searchTerm = $('#user-search').val().toLowerCase();
const rows = $('.users-table tbody tr');
rows.each(function() {
const row = $(this);
const text = row.text().toLowerCase();
if (text.includes(searchTerm)) {
row.show();
} else {
row.hide();
}
});
}
// Real-time search
$('#user-search').on('input', function() {
filterUsers();
});
// Export functionality
function exportUsers() {
window.location.href = '/admin/export/users';
}
function exportEvents() {
window.location.href = '/admin/export/events';
}