This commit is contained in:
2026-03-20 16:30:45 +07:00
parent e51f34d7be
commit d935b7374d
11 changed files with 438 additions and 31 deletions

View File

@@ -10,6 +10,7 @@
this.currentContainer = '';
this.logStream = null;
this.logsBuffer = [];
this.currentSettings = null;
this.currentPage = 1;
this.limit = 10;
this.editingRecord = null;
@@ -152,6 +153,7 @@
document.getElementById('logsButton').classList.toggle('hidden', !this.getPermissions().canViewLogs);
document.getElementById('usersButton').classList.toggle('hidden', !this.getPermissions().canManageUsers);
document.getElementById('backupsButton').classList.toggle('hidden', !this.getPermissions().canManageUsers);
document.getElementById('settingsButton').classList.toggle('hidden', !this.getPermissions().canManageUsers);
document.getElementById('auditButton').classList.toggle('hidden', !this.getPermissions().canManageUsers);
document.querySelector('button[onclick="app.showSQLPanel()"]').style.display = this.getPermissions().canRunSql ? '' : 'none';
document.querySelector('button[onclick="app.showCreateTableModal()"]').style.display = this.getPermissions().canCreate ? '' : 'none';
@@ -1226,6 +1228,11 @@
document.getElementById('backupsModal').classList.remove('hidden');
}
async showSettingsModal() {
await this.loadSettings();
document.getElementById('settingsModal').classList.remove('hidden');
}
async loadBackups() {
try {
const response = await fetch('/api/backups');
@@ -1239,7 +1246,7 @@
<div class="border border-slate-200 rounded-xl p-4 flex items-center justify-between gap-4">
<div>
<div class="font-medium text-slate-800">${backup.filename}</div>
<div class="text-sm text-slate-500">${backup.createdAt} · ${backup.size} bytes</div>
<div class="text-sm text-slate-500">${backup.createdAt} - ${backup.kind} - ${backup.size} bytes</div>
</div>
<a href="/api/backups/${encodeURIComponent(backup.filename)}/download" class="px-4 py-2 bg-slate-100 text-slate-700 rounded-lg">Download</a>
</div>
@@ -1267,6 +1274,66 @@
}
}
async loadSettings() {
try {
const response = await fetch('/api/settings');
const settings = await response.json();
if (!response.ok) {
throw new Error(settings.error || 'Failed to load settings');
}
this.currentSettings = settings;
document.getElementById('settingsBackupsEnabled').checked = Boolean(settings.backups?.enabled);
document.getElementById('settingsBackupTime').value = `${String(settings.backups?.hour ?? 3).padStart(2, '0')}:${String(settings.backups?.minute ?? 0).padStart(2, '0')}`;
document.getElementById('settingsKeepLast').value = settings.backups?.keepLast ?? 14;
document.getElementById('settingsIncludeAppSnapshot').checked = settings.backups?.includeAppSnapshot !== false;
document.getElementById('settingsTelegramEnabled').checked = Boolean(settings.telegram?.enabled);
document.getElementById('settingsTelegramToken').value = settings.telegram?.botToken || '';
document.getElementById('settingsTelegramChatId').value = settings.telegram?.chatId || '';
} catch (err) {
this.showToast(err.message, 'error');
}
}
async saveSettings() {
const [hour, minute] = (document.getElementById('settingsBackupTime').value || '03:00').split(':').map(Number);
const payload = {
backups: {
enabled: document.getElementById('settingsBackupsEnabled').checked,
hour,
minute,
keepLast: Number(document.getElementById('settingsKeepLast').value || 14),
includeAppSnapshot: document.getElementById('settingsIncludeAppSnapshot').checked,
},
telegram: {
enabled: document.getElementById('settingsTelegramEnabled').checked,
botToken: document.getElementById('settingsTelegramToken').value.trim(),
chatId: document.getElementById('settingsTelegramChatId').value.trim(),
},
};
try {
const response = await fetch('/api/settings', {
method: 'PUT',
headers: {
'Content-Type': 'application/json',
'X-Request-Source': 'WEB',
},
body: JSON.stringify(payload),
});
const result = await response.json();
if (!response.ok) {
throw new Error(result.error || 'Failed to save settings');
}
this.currentSettings = result.settings;
this.showToast('Settings saved', 'success');
this.closeModal('settingsModal');
} catch (err) {
this.showToast(err.message, 'error');
}
}
async loadAuditLog() {
try {
const response = await fetch('/api/audit');