361 lines
12 KiB
JavaScript
361 lines
12 KiB
JavaScript
let currentUser = null;
|
|
let users = [];
|
|
let filteredUsers = [];
|
|
|
|
document.addEventListener('DOMContentLoaded', function() {
|
|
checkAuth();
|
|
setupEventListeners();
|
|
});
|
|
|
|
async function checkAuth() {
|
|
try {
|
|
const response = await fetch('/api/user');
|
|
if (response.ok) {
|
|
const data = await response.json();
|
|
currentUser = data.user;
|
|
|
|
if (currentUser.role !== 'admin') {
|
|
window.location.href = '/';
|
|
return;
|
|
}
|
|
|
|
showAdminInterface();
|
|
} else {
|
|
showLoginInterface();
|
|
}
|
|
} catch (error) {
|
|
showLoginInterface();
|
|
}
|
|
}
|
|
|
|
function showLoginInterface() {
|
|
document.getElementById('login-modal').style.display = 'block';
|
|
document.querySelector('.admin-container').style.display = 'none';
|
|
}
|
|
|
|
function showAdminInterface() {
|
|
document.getElementById('login-modal').style.display = 'none';
|
|
document.querySelector('.admin-container').style.display = 'block';
|
|
|
|
let userInfo = `Администратор: ${currentUser.name}`;
|
|
if (currentUser.auth_type === 'ldap') {
|
|
userInfo += ` (LDAP)`;
|
|
}
|
|
|
|
document.getElementById('current-user').textContent = userInfo;
|
|
|
|
loadUsers();
|
|
loadDashboardStats();
|
|
}
|
|
|
|
function setupEventListeners() {
|
|
document.getElementById('login-form').addEventListener('submit', login);
|
|
document.getElementById('edit-user-form').addEventListener('submit', updateUser);
|
|
}
|
|
|
|
async function login(event) {
|
|
event.preventDefault();
|
|
|
|
const login = document.getElementById('login').value;
|
|
const password = document.getElementById('password').value;
|
|
|
|
try {
|
|
const response = await fetch('/api/login', {
|
|
method: 'POST',
|
|
headers: {
|
|
'Content-Type': 'application/json',
|
|
},
|
|
body: JSON.stringify({ login, password })
|
|
});
|
|
|
|
if (response.ok) {
|
|
const data = await response.json();
|
|
currentUser = data.user;
|
|
|
|
if (currentUser.role !== 'admin') {
|
|
window.location.href = '/';
|
|
return;
|
|
}
|
|
|
|
showAdminInterface();
|
|
} else {
|
|
const error = await response.json();
|
|
alert(error.error || 'Ошибка входа');
|
|
}
|
|
} catch (error) {
|
|
console.error('Ошибка:', error);
|
|
alert('Ошибка подключения к серверу');
|
|
}
|
|
}
|
|
|
|
async function logout() {
|
|
try {
|
|
await fetch('/api/logout', { method: 'POST' });
|
|
currentUser = null;
|
|
showLoginInterface();
|
|
} catch (error) {
|
|
console.error('Ошибка выхода:', error);
|
|
}
|
|
}
|
|
|
|
function showAdminSection(sectionName) {
|
|
document.querySelectorAll('.admin-tab').forEach(tab => {
|
|
tab.classList.remove('active');
|
|
});
|
|
|
|
document.querySelectorAll('.admin-section').forEach(section => {
|
|
section.classList.remove('active');
|
|
});
|
|
|
|
document.querySelector(`.admin-tab[onclick="showAdminSection('${sectionName}')"]`).classList.add('active');
|
|
document.getElementById(`admin-${sectionName}`).classList.add('active');
|
|
|
|
if (sectionName === 'users') {
|
|
loadUsers();
|
|
} else if (sectionName === 'dashboard') {
|
|
loadDashboardStats();
|
|
}
|
|
}
|
|
|
|
async function loadUsers() {
|
|
try {
|
|
const response = await fetch('/admin/users');
|
|
if (!response.ok) {
|
|
throw new Error('Ошибка загрузки пользователей');
|
|
}
|
|
users = await response.json();
|
|
filteredUsers = [...users];
|
|
renderUsersTable();
|
|
} catch (error) {
|
|
console.error('Ошибка загрузки пользователей:', error);
|
|
showError('users-table-body', 'Ошибка загрузки пользователей');
|
|
}
|
|
}
|
|
|
|
async function loadDashboardStats() {
|
|
try {
|
|
const response = await fetch('/admin/stats');
|
|
if (!response.ok) {
|
|
throw new Error('Ошибка загрузки статистики');
|
|
}
|
|
|
|
const stats = await response.json();
|
|
updateStatsUI(stats);
|
|
} catch (error) {
|
|
console.error('Ошибка загрузки статистики:', error);
|
|
}
|
|
}
|
|
|
|
function updateStatsUI(stats) {
|
|
// Задачи
|
|
document.getElementById('total-tasks').textContent = stats.totalTasks;
|
|
document.getElementById('active-tasks').textContent = stats.activeTasks;
|
|
document.getElementById('closed-tasks').textContent = stats.closedTasks;
|
|
document.getElementById('deleted-tasks').textContent = stats.deletedTasks;
|
|
|
|
// Процент активных задач
|
|
if (stats.totalTasks > 0) {
|
|
const activePercentage = Math.round((stats.activeTasks / stats.totalTasks) * 100);
|
|
document.getElementById('active-tasks-bar').style.width = `${activePercentage}%`;
|
|
}
|
|
|
|
// Назначения
|
|
document.getElementById('total-assignments').textContent = stats.totalAssignments;
|
|
document.getElementById('assigned-count').textContent = stats.assignedCount;
|
|
document.getElementById('in-progress-count').textContent = stats.inProgressCount;
|
|
document.getElementById('completed-count').textContent = stats.completedCount;
|
|
document.getElementById('overdue-count').textContent = stats.overdueCount;
|
|
document.getElementById('rework-count').textContent = stats.reworkCount;
|
|
|
|
// Пользователи
|
|
document.getElementById('total-users').textContent = stats.totalUsers;
|
|
document.getElementById('admin-users').textContent = stats.adminUsers;
|
|
document.getElementById('teacher-users').textContent = stats.teacherUsers;
|
|
document.getElementById('ldap-users').textContent = stats.ldapUsers;
|
|
document.getElementById('local-users').textContent = stats.localUsers;
|
|
|
|
// Файлы
|
|
document.getElementById('total-files').textContent = stats.totalFiles;
|
|
const fileSizeMB = (stats.totalFilesSize / 1024 / 1024).toFixed(2);
|
|
document.getElementById('total-files-size').textContent = `${fileSizeMB} MB`;
|
|
|
|
}
|
|
|
|
function searchUsers() {
|
|
const search = document.getElementById('user-search').value.toLowerCase();
|
|
filteredUsers = users.filter(user =>
|
|
user.login.toLowerCase().includes(search) ||
|
|
user.name.toLowerCase().includes(search) ||
|
|
user.email.toLowerCase().includes(search) ||
|
|
user.role.toLowerCase().includes(search) ||
|
|
user.auth_type.toLowerCase().includes(search)
|
|
);
|
|
renderUsersTable();
|
|
}
|
|
|
|
function renderUsersTable() {
|
|
const tbody = document.getElementById('users-table-body');
|
|
|
|
if (!filteredUsers || filteredUsers.length === 0) {
|
|
tbody.innerHTML = '<tr><td colspan="9" class="loading">Пользователи не найдены</td></tr>';
|
|
return;
|
|
}
|
|
|
|
tbody.innerHTML = filteredUsers.map(user => `
|
|
<tr>
|
|
<td>${user.id}</td>
|
|
<td>
|
|
${user.login}
|
|
${user.auth_type === 'ldap' ? '<span class="ldap-badge">LDAP</span>' : ''}
|
|
</td>
|
|
<td>${user.name}</td>
|
|
<td>${user.email}</td>
|
|
<td>
|
|
${user.role === 'admin' ? 'Администратор' : 'Учитель'}
|
|
${user.role === 'admin' ? '<span class="admin-badge">ADMIN</span>' : ''}
|
|
</td>
|
|
<td>${user.auth_type === 'ldap' ? 'LDAP' : 'Локальная'}</td>
|
|
<td>${formatDate(user.created_at)}</td>
|
|
<td>${user.last_login ? formatDateTime(user.last_login) : 'Никогда'}</td>
|
|
<td class="user-actions">
|
|
<button class="edit-btn" onclick="openEditUserModal(${user.id})" title="Редактировать">✏️</button>
|
|
<button class="delete-btn" onclick="deleteUser(${user.id})" title="Удалить" ${user.id === currentUser.id ? 'disabled' : ''}>🗑️</button>
|
|
</td>
|
|
</tr>
|
|
`).join('');
|
|
}
|
|
|
|
async function openEditUserModal(userId) {
|
|
try {
|
|
const response = await fetch(`/admin/users/${userId}`);
|
|
if (!response.ok) {
|
|
throw new Error('Ошибка загрузки пользователя');
|
|
}
|
|
|
|
const user = await response.json();
|
|
|
|
document.getElementById('edit-user-id').value = user.id;
|
|
document.getElementById('edit-login').value = user.login;
|
|
document.getElementById('edit-name').value = user.name;
|
|
document.getElementById('edit-email').value = user.email;
|
|
document.getElementById('edit-role').value = user.role;
|
|
document.getElementById('edit-auth-type').value = user.auth_type;
|
|
document.getElementById('edit-groups').value = user.groups || '[]';
|
|
document.getElementById('edit-description').value = user.description || '';
|
|
|
|
document.getElementById('edit-user-modal').style.display = 'block';
|
|
} catch (error) {
|
|
console.error('Ошибка:', error);
|
|
alert('Ошибка загрузки пользователя');
|
|
}
|
|
}
|
|
|
|
function closeEditUserModal() {
|
|
document.getElementById('edit-user-modal').style.display = 'none';
|
|
}
|
|
|
|
async function updateUser(event) {
|
|
event.preventDefault();
|
|
|
|
const userId = document.getElementById('edit-user-id').value;
|
|
const login = document.getElementById('edit-login').value;
|
|
const name = document.getElementById('edit-name').value;
|
|
const email = document.getElementById('edit-email').value;
|
|
const role = document.getElementById('edit-role').value;
|
|
const auth_type = document.getElementById('edit-auth-type').value;
|
|
const groups = document.getElementById('edit-groups').value;
|
|
const description = document.getElementById('edit-description').value;
|
|
|
|
if (!login || !name || !email) {
|
|
alert('Заполните обязательные поля');
|
|
return;
|
|
}
|
|
|
|
const userData = {
|
|
login,
|
|
name,
|
|
email,
|
|
role,
|
|
auth_type,
|
|
groups: groups || '[]',
|
|
description
|
|
};
|
|
|
|
try {
|
|
const response = await fetch(`/admin/users/${userId}`, {
|
|
method: 'PUT',
|
|
headers: {
|
|
'Content-Type': 'application/json',
|
|
},
|
|
body: JSON.stringify(userData)
|
|
});
|
|
|
|
if (response.ok) {
|
|
alert('Пользователь успешно обновлен!');
|
|
closeEditUserModal();
|
|
loadUsers();
|
|
loadDashboardStats();
|
|
} else {
|
|
const error = await response.json();
|
|
alert(error.error || 'Ошибка обновления пользователя');
|
|
}
|
|
} catch (error) {
|
|
console.error('Ошибка:', error);
|
|
alert('Ошибка обновления пользователя');
|
|
}
|
|
}
|
|
|
|
async function deleteUser(userId) {
|
|
if (userId === currentUser.id) {
|
|
alert('Нельзя удалить самого себя');
|
|
return;
|
|
}
|
|
|
|
if (!confirm('Вы уверены, что хотите удалить этого пользователя?')) {
|
|
return;
|
|
}
|
|
|
|
try {
|
|
const response = await fetch(`/admin/users/${userId}`, {
|
|
method: 'DELETE'
|
|
});
|
|
|
|
if (response.ok) {
|
|
alert('Пользователь успешно удален!');
|
|
loadUsers();
|
|
loadDashboardStats();
|
|
} else {
|
|
const error = await response.json();
|
|
alert(error.error || 'Ошибка удаления пользователя');
|
|
}
|
|
} catch (error) {
|
|
console.error('Ошибка:', error);
|
|
alert('Ошибка удаления пользователя');
|
|
}
|
|
}
|
|
|
|
function formatDateTime(dateTimeString) {
|
|
if (!dateTimeString) return '';
|
|
const date = new Date(dateTimeString);
|
|
return date.toLocaleString('ru-RU');
|
|
}
|
|
|
|
function formatDate(dateString) {
|
|
if (!dateString) return '';
|
|
const date = new Date(dateString);
|
|
return date.toLocaleDateString('ru-RU');
|
|
}
|
|
|
|
function showError(elementId, message) {
|
|
const element = document.getElementById(elementId);
|
|
if (element) {
|
|
element.innerHTML = `<tr><td colspan="9" class="error">${message}</td></tr>`;
|
|
}
|
|
}
|
|
|
|
// Автоматическое обновление статистики каждые 30 секунд
|
|
setInterval(() => {
|
|
if (document.getElementById('admin-dashboard').classList.contains('active')) {
|
|
loadDashboardStats();
|
|
}
|
|
}, 30000); |