init
This commit is contained in:
228
public/js/app.js
Normal file
228
public/js/app.js
Normal file
@@ -0,0 +1,228 @@
|
||||
// Main Application Handler
|
||||
class Application {
|
||||
constructor() {
|
||||
this.init();
|
||||
}
|
||||
|
||||
async init() {
|
||||
// Wait for auth check
|
||||
const isAuth = await auth.checkAuth();
|
||||
|
||||
if (isAuth) {
|
||||
// Redirect to dashboard
|
||||
if (window.location.hash === '' || window.location.hash === '#login') {
|
||||
window.location.hash = '#dashboard';
|
||||
}
|
||||
} else {
|
||||
// Redirect to login
|
||||
window.location.hash = '#login';
|
||||
}
|
||||
}
|
||||
|
||||
loadDashboardData() {
|
||||
this.loadStats();
|
||||
this.loadTablesList();
|
||||
}
|
||||
|
||||
async loadStats() {
|
||||
try {
|
||||
const stats = await api.getDatabaseStats();
|
||||
document.getElementById('statsTableCount').textContent = stats.tableCount || 0;
|
||||
document.getElementById('statsRecordCount').textContent = stats.recordCount || 0;
|
||||
document.getElementById('statsUserCount').textContent = stats.userCount || 0;
|
||||
document.getElementById('statsDbSize').textContent = stats.dbSize || '-';
|
||||
} catch (error) {
|
||||
console.error('Failed to load stats:', error);
|
||||
}
|
||||
}
|
||||
|
||||
async loadTablesList() {
|
||||
try {
|
||||
const tables = await api.getTables();
|
||||
const tablesList = document.getElementById('tablesList');
|
||||
|
||||
if (tables.length === 0) {
|
||||
tablesList.innerHTML = '<p class="text-slate-500 dark:text-slate-400 text-sm">Таблицы не найдены</p>';
|
||||
return;
|
||||
}
|
||||
|
||||
tablesList.innerHTML = tables.map(table => `
|
||||
<div class="flex items-center justify-between p-3 bg-slate-50 dark:bg-slate-800 rounded-lg hover:bg-slate-100 dark:hover:bg-slate-700 transition-colors cursor-pointer" onclick="window.location.hash='#tables'">
|
||||
<div class="flex items-center gap-2">
|
||||
<i data-lucide="table" class="w-4 h-4 text-blue-600 dark:text-blue-400"></i>
|
||||
<span class="font-medium text-slate-900 dark:text-white">${table.name}</span>
|
||||
</div>
|
||||
<span class="text-xs text-slate-500 dark:text-slate-400">${table.recordCount || 0} записей</span>
|
||||
</div>
|
||||
`).join('');
|
||||
|
||||
if (typeof lucide !== 'undefined') {
|
||||
lucide.createIcons();
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('Failed to load tables:', error);
|
||||
}
|
||||
}
|
||||
|
||||
loadAdminPanel() {
|
||||
this.loadUsers();
|
||||
}
|
||||
|
||||
async loadUsers() {
|
||||
try {
|
||||
const users = await api.getUsers();
|
||||
const usersList = document.getElementById('usersList');
|
||||
|
||||
if (!users || users.length === 0) {
|
||||
usersList.innerHTML = '<tr><td colspan="5" class="py-8 px-4 text-center text-slate-500 dark:text-slate-400">Пользователи не найдены</td></tr>';
|
||||
return;
|
||||
}
|
||||
|
||||
usersList.innerHTML = users.map(user => `
|
||||
<tr>
|
||||
<td class="py-3 px-4 font-medium text-slate-900 dark:text-white">${user.name}</td>
|
||||
<td class="py-3 px-4 text-slate-600 dark:text-slate-400 hidden sm:table-cell text-sm">${user.email}</td>
|
||||
<td class="py-3 px-4 text-slate-600 dark:text-slate-400">
|
||||
<span class="px-2 py-1 rounded bg-blue-100 dark:bg-blue-900/30 text-blue-700 dark:text-blue-300 text-xs font-medium">${this.getRoleName(user.role)}</span>
|
||||
</td>
|
||||
<td class="py-3 px-4">
|
||||
<span class="inline-flex items-center gap-1 px-2 py-1 rounded-full text-xs font-semibold ${user.active ? 'bg-green-100 dark:bg-green-900/30 text-green-700 dark:text-green-400' : 'bg-slate-100 dark:bg-slate-800 text-slate-700 dark:text-slate-400'}">
|
||||
<i data-lucide="circle" class="w-2 h-2"></i>
|
||||
${user.active ? 'Активен' : 'Неактивен'}
|
||||
</span>
|
||||
</td>
|
||||
<td class="py-3 px-4 text-right">
|
||||
<div class="flex items-center justify-end gap-2">
|
||||
<button onclick="app.editUser(${user.id})" class="p-1 hover:bg-blue-100 dark:hover:bg-blue-900/30 rounded text-blue-600 dark:text-blue-400" title="Редактировать">
|
||||
<i data-lucide="edit" class="w-4 h-4"></i>
|
||||
</button>
|
||||
<button onclick="app.deleteUser(${user.id})" class="p-1 hover:bg-red-100 dark:hover:bg-red-900/30 rounded text-red-600 dark:text-red-400" title="Удалить">
|
||||
<i data-lucide="trash" class="w-4 h-4"></i>
|
||||
</button>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
`).join('');
|
||||
|
||||
if (typeof lucide !== 'undefined') {
|
||||
lucide.createIcons();
|
||||
}
|
||||
|
||||
this.setupAdminPanelHandlers();
|
||||
} catch (error) {
|
||||
console.error('Failed to load users:', error);
|
||||
}
|
||||
}
|
||||
|
||||
setupAdminPanelHandlers() {
|
||||
// Add user button
|
||||
const addUserBtn = document.getElementById('addUserBtn');
|
||||
if (addUserBtn) {
|
||||
addUserBtn.onclick = () => this.showUserModal(null);
|
||||
}
|
||||
|
||||
// User modal controls
|
||||
const userModal = document.getElementById('userModal');
|
||||
const closeBtn = document.getElementById('closeUserModal');
|
||||
const cancelBtn = document.getElementById('cancelUserEdit');
|
||||
const userForm = document.getElementById('userForm');
|
||||
|
||||
if (closeBtn) closeBtn.onclick = () => userModal.classList.add('hidden');
|
||||
if (cancelBtn) cancelBtn.onclick = () => userModal.classList.add('hidden');
|
||||
|
||||
if (userForm) {
|
||||
userForm.onsubmit = (e) => this.handleUserFormSubmit(e);
|
||||
}
|
||||
}
|
||||
|
||||
showUserModal(userId) {
|
||||
const userModal = document.getElementById('userModal');
|
||||
const userForm = document.getElementById('userForm');
|
||||
const userModalTitle = document.getElementById('userModalTitle');
|
||||
|
||||
userForm.reset();
|
||||
userForm.dataset.userId = userId || '';
|
||||
|
||||
if (userId) {
|
||||
userModalTitle.textContent = 'Редактировать пользователя';
|
||||
// Load user data
|
||||
// TODO: implement
|
||||
} else {
|
||||
userModalTitle.textContent = 'Добавить пользователя';
|
||||
}
|
||||
|
||||
userModal.classList.remove('hidden');
|
||||
}
|
||||
|
||||
async handleUserFormSubmit(e) {
|
||||
e.preventDefault();
|
||||
|
||||
const formData = {
|
||||
name: document.getElementById('userNameInput').value,
|
||||
email: document.getElementById('userEmailInput').value,
|
||||
role: document.getElementById('userRoleSelect').value,
|
||||
password: document.getElementById('userPasswordInput').value
|
||||
};
|
||||
|
||||
const userId = e.target.dataset.userId;
|
||||
|
||||
try {
|
||||
if (userId) {
|
||||
await api.updateUser(userId, formData);
|
||||
} else {
|
||||
await api.createUser(formData);
|
||||
}
|
||||
|
||||
document.getElementById('userModal').classList.add('hidden');
|
||||
this.loadUsers();
|
||||
} catch (error) {
|
||||
alert('Ошибка: ' + error.message);
|
||||
}
|
||||
}
|
||||
|
||||
async editUser(userId) {
|
||||
// TODO: implement
|
||||
this.showUserModal(userId);
|
||||
}
|
||||
|
||||
async deleteUser(userId) {
|
||||
if (confirm('Вы уверены, что хотите удалить этого пользователя?')) {
|
||||
try {
|
||||
await api.deleteUser(userId);
|
||||
this.loadUsers();
|
||||
} catch (error) {
|
||||
alert('Ошибка: ' + error.message);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
getRoleName(role) {
|
||||
const names = {
|
||||
'superadmin': 'Суперадминистратор',
|
||||
'admin': 'Администратор',
|
||||
'moderator': 'Модератор',
|
||||
'viewer': 'Только просмотр'
|
||||
};
|
||||
return names[role] || role;
|
||||
}
|
||||
}
|
||||
|
||||
// Initialize application
|
||||
const app = new Application();
|
||||
|
||||
// Update content when route changes
|
||||
document.addEventListener('DOMContentLoaded', () => {
|
||||
window.addEventListener('hashchange', () => {
|
||||
const currentRoute = window.location.hash.slice(1);
|
||||
|
||||
// Load dashboard data
|
||||
if (currentRoute.includes('dashboard') || currentRoute === '') {
|
||||
app.loadDashboardData();
|
||||
}
|
||||
|
||||
// Load admin panel
|
||||
if (currentRoute.includes('admin')) {
|
||||
app.loadAdminPanel();
|
||||
}
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user