Files
minicrm/public/admin-script.js
2026-02-07 00:56:09 +05:00

451 lines
15 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
// admin-script.js (обновленный)
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();
// Если дашборд активен, рендерим его
if (document.getElementById('admin-dashboard').classList.contains('active')) {
if (typeof renderDashboard === 'function') {
renderDashboard();
}
}
// Если статистика активна, рендерим ее
if (document.getElementById('admin-stats-section').classList.contains('active')) {
if (typeof renderStatsSection === 'function') {
renderStatsSection();
}
}
}
function setupEventListeners() {
const loginForm = document.getElementById('login-form');
const editUserForm = document.getElementById('edit-user-form');
if (loginForm) {
loginForm.addEventListener('submit', login);
}
if (editUserForm) {
editUserForm.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) {
console.log('showAdminSection called with:', sectionName);
// Убираем активный класс у всех вкладок
document.querySelectorAll('.admin-tab').forEach(tab => {
tab.classList.remove('active');
});
// Убираем активный класс у всех секций
document.querySelectorAll('.admin-section').forEach(section => {
section.classList.remove('active');
});
// Находим и активируем соответствующую вкладку
const tabs = document.querySelectorAll('.admin-tab');
let tabFound = false;
tabs.forEach(tab => {
const onclick = tab.getAttribute('onclick');
if (onclick && onclick.includes(`showAdminSection('${sectionName}')`)) {
tab.classList.add('active');
tabFound = true;
}
});
// Если не нашли по onclick, ищем по тексту
if (!tabFound) {
tabs.forEach(tab => {
const tabText = tab.textContent.toLowerCase();
if (tabText.includes(sectionName.toLowerCase())) {
tab.classList.add('active');
}
});
}
// Активируем соответствующую секцию
const sectionId = `admin-${sectionName}-section`;
let section = document.getElementById(sectionId);
// Если не нашли по такому ID, пробуем другие варианты
if (!section) {
if (sectionName === 'users') {
section = document.getElementById('admin-users-section');
} else if (sectionName === 'dashboard') {
section = document.getElementById('admin-dashboard');
} else if (sectionName === 'stats') {
section = document.getElementById('admin-stats-section');
} else {
// Пробуем найти по частичному совпадению
const sections = document.querySelectorAll('.admin-section');
sections.forEach(s => {
if (s.id.includes(sectionName)) {
section = s;
}
});
}
}
if (section) {
section.classList.add('active');
console.log('Activated section:', section.id);
} else {
console.error('Section not found for:', sectionName);
}
// Загружаем данные для активной секции
setTimeout(() => {
if (sectionName === 'users') {
console.log('Loading users...');
loadUsers();
} else if (sectionName === 'dashboard') {
console.log('Loading dashboard...');
if (typeof renderDashboard === 'function') {
renderDashboard();
}
} else if (sectionName === 'stats') {
console.log('Loading stats...');
if (typeof renderStatsSection === 'function') {
renderStatsSection();
}
}
}, 50);
}
async function loadUsers() {
try {
const tbody = document.getElementById('users-table-body');
if (tbody) {
tbody.innerHTML = '<tr><td colspan="9" class="loading">Загрузка пользователей...</td></tr>';
}
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', 'Ошибка загрузки пользователей');
}
}
function searchUsers() {
const searchInput = document.getElementById('user-search');
if (!searchInput) return;
const search = searchInput.value.toLowerCase();
filteredUsers = users.filter(user =>
(user.login && user.login.toLowerCase().includes(search)) ||
(user.name && user.name.toLowerCase().includes(search)) ||
(user.email && user.email.toLowerCase().includes(search)) ||
(user.role && user.role.toLowerCase().includes(search)) ||
(user.auth_type && user.auth_type.toLowerCase().includes(search))
);
renderUsersTable();
}
function renderUsersTable() {
const tbody = document.getElementById('users-table-body');
if (!tbody) return;
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 || 'Нет 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 || '';
const modal = document.getElementById('edit-user-modal');
if (modal) {
modal.style.display = 'block';
}
} catch (error) {
console.error('Ошибка:', error);
alert('Ошибка загрузки пользователя');
}
}
function closeEditUserModal() {
const modal = document.getElementById('edit-user-modal');
if (modal) {
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();
// Обновляем статистику если она видна
if (document.getElementById('admin-dashboard')?.classList.contains('active')) {
if (typeof loadDashboardStats === 'function') {
loadDashboardStats();
}
}
if (document.getElementById('admin-stats-section')?.classList.contains('active')) {
if (typeof loadUsersStats === 'function') {
loadUsersStats();
}
if (typeof loadOverallStats === 'function') {
loadOverallStats();
}
}
} 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();
// Обновляем статистику если она видна
if (document.getElementById('admin-dashboard')?.classList.contains('active')) {
if (typeof loadDashboardStats === 'function') {
loadDashboardStats();
}
}
if (document.getElementById('admin-stats-section')?.classList.contains('active')) {
if (typeof loadUsersStats === 'function') {
loadUsersStats();
}
if (typeof loadOverallStats === 'function') {
loadOverallStats();
}
}
} else {
const error = await response.json();
alert(error.error || 'Ошибка удаления пользователя');
}
} catch (error) {
console.error('Ошибка:', error);
alert('Ошибка удаления пользователя');
}
}
function formatDateTime(dateTimeString) {
if (!dateTimeString) return '';
try {
const date = new Date(dateTimeString);
return date.toLocaleString('ru-RU');
} catch (e) {
return dateTimeString;
}
}
function formatDate(dateString) {
if (!dateString) return '';
try {
const date = new Date(dateString);
return date.toLocaleDateString('ru-RU');
} catch (e) {
return dateString;
}
}
function showError(elementId, message) {
const element = document.getElementById(elementId);
if (element) {
element.innerHTML = `<tr><td colspan="9" class="error">${message}</td></tr>`;
}
}
// Делаем функции глобально доступными
window.logout = logout;
window.showAdminSection = showAdminSection;
window.searchUsers = searchUsers;
window.loadUsers = loadUsers;
window.openEditUserModal = openEditUserModal;
window.closeEditUserModal = closeEditUserModal;
window.updateUser = updateUser;
window.deleteUser = deleteUser;