updated documentation folder

This commit is contained in:
Quality System Admin
2025-11-03 21:17:10 +02:00
parent 8d47e6e82d
commit 1ade0b5681
29 changed files with 6113 additions and 32 deletions

View File

@@ -50,6 +50,72 @@
Recommended: Use the simplified user management for easier administration
</small>
</div>
{% if session.role in ['superadmin', 'admin'] %}
<div class="card" style="margin-top: 32px;">
<h3>💾 Database Backup Management</h3>
<p><strong>Automated Backup System:</strong> Schedule and manage database backups</p>
<!-- Backup Controls -->
<div style="margin-top: 20px; padding: 15px; background: #f5f5f5; border-radius: 8px;">
<h4 style="margin-top: 0;">Quick Actions</h4>
<button id="backup-now-btn" class="btn" style="background-color: #4caf50; color: white; margin-right: 10px;">
⚡ Backup Now
</button>
<button id="refresh-backups-btn" class="btn" style="background-color: #2196f3; color: white;">
🔄 Refresh List
</button>
</div>
<!-- Schedule Configuration -->
<div style="margin-top: 20px; padding: 15px; background: #f9f9f9; border-radius: 8px;">
<h4 style="margin-top: 0;">Backup Schedule</h4>
<form id="backup-schedule-form" style="display: grid; grid-template-columns: 1fr 1fr; gap: 15px;">
<div>
<label for="schedule-enabled">
<input type="checkbox" id="schedule-enabled" name="enabled"> Enable Scheduled Backups
</label>
</div>
<div>
<label for="schedule-time">Backup Time:</label>
<input type="time" id="schedule-time" name="time" value="02:00">
</div>
<div>
<label for="schedule-frequency">Frequency:</label>
<select id="schedule-frequency" name="frequency">
<option value="daily">Daily</option>
<option value="weekly">Weekly</option>
<option value="monthly">Monthly</option>
</select>
</div>
<div>
<label for="retention-days">Keep backups for (days):</label>
<input type="number" id="retention-days" name="retention_days" value="30" min="1" max="365">
</div>
<div style="grid-column: span 2;">
<button type="submit" class="btn" style="background-color: #ff9800; color: white;">
💾 Save Schedule
</button>
</div>
</form>
</div>
<!-- Backup List -->
<div style="margin-top: 20px;">
<h4>Available Backups</h4>
<div id="backup-list" style="max-height: 400px; overflow-y: auto;">
<p style="text-align: center; color: #999;">Loading backups...</p>
</div>
</div>
<!-- Backup Path Info -->
<div style="margin-top: 15px; padding: 10px; background: #e3f2fd; border-left: 4px solid #2196f3; border-radius: 4px;">
<strong> Backup Location:</strong> <code id="backup-path-display">/srv/quality_app/backups</code>
<br>
<small>Configure backup path in docker-compose.yml (BACKUP_PATH environment variable)</small>
</div>
</div>
{% endif %}
</div>
<!-- Popup for creating/editing a user -->
@@ -136,5 +202,162 @@ Array.from(document.getElementsByClassName('delete-user-btn')).forEach(function(
document.getElementById('close-delete-popup-btn').onclick = function() {
document.getElementById('delete-user-popup').style.display = 'none';
};
// ========================================
// Database Backup Management Functions
// ========================================
// Load backup schedule on page load
function loadBackupSchedule() {
fetch('/api/backup/schedule')
.then(response => response.json())
.then(data => {
if (data.success) {
document.getElementById('schedule-enabled').checked = data.schedule.enabled;
document.getElementById('schedule-time').value = data.schedule.time;
document.getElementById('schedule-frequency').value = data.schedule.frequency;
document.getElementById('retention-days').value = data.schedule.retention_days;
}
})
.catch(error => console.error('Error loading schedule:', error));
}
// Load backup list
function loadBackupList() {
const backupList = document.getElementById('backup-list');
if (!backupList) return;
backupList.innerHTML = '<p style="text-align: center; color: #999;">Loading backups...</p>';
fetch('/api/backup/list')
.then(response => response.json())
.then(data => {
if (data.success && data.backups.length > 0) {
let html = '<table style="width: 100%; border-collapse: collapse;">';
html += '<thead><tr style="background: #f0f0f0;"><th style="padding: 10px; text-align: left;">Filename</th><th>Size</th><th>Created</th><th>Actions</th></tr></thead>';
html += '<tbody>';
data.backups.forEach(backup => {
html += `<tr style="border-bottom: 1px solid #ddd;">
<td style="padding: 10px;">${backup.filename}</td>
<td style="text-align: center;">${backup.size_mb} MB</td>
<td style="text-align: center;">${backup.created}</td>
<td style="text-align: center;">
<button onclick="downloadBackup('${backup.filename}')" class="btn" style="background: #2196f3; color: white; padding: 5px 10px; margin: 2px;">⬇️ Download</button>
<button onclick="deleteBackup('${backup.filename}')" class="btn" style="background: #f44336; color: white; padding: 5px 10px; margin: 2px;">🗑️ Delete</button>
</td>
</tr>`;
});
html += '</tbody></table>';
backupList.innerHTML = html;
} else {
backupList.innerHTML = '<p style="text-align: center; color: #999;">No backups available</p>';
}
})
.catch(error => {
console.error('Error loading backups:', error);
backupList.innerHTML = '<p style="text-align: center; color: #f44336;">Error loading backups</p>';
});
}
// Backup now button
document.getElementById('backup-now-btn')?.addEventListener('click', function() {
const btn = this;
btn.disabled = true;
btn.innerHTML = '⏳ Creating backup...';
fetch('/api/backup/create', {
method: 'POST'
})
.then(response => response.json())
.then(data => {
if (data.success) {
alert('✅ ' + data.message + '\nFile: ' + data.filename + '\nSize: ' + data.size);
loadBackupList();
} else {
alert('❌ ' + data.message);
}
btn.disabled = false;
btn.innerHTML = '⚡ Backup Now';
})
.catch(error => {
console.error('Error creating backup:', error);
alert('❌ Failed to create backup');
btn.disabled = false;
btn.innerHTML = '⚡ Backup Now';
});
});
// Refresh backups button
document.getElementById('refresh-backups-btn')?.addEventListener('click', function() {
loadBackupList();
});
// Save schedule form
document.getElementById('backup-schedule-form')?.addEventListener('submit', function(e) {
e.preventDefault();
const formData = {
enabled: document.getElementById('schedule-enabled').checked,
time: document.getElementById('schedule-time').value,
frequency: document.getElementById('schedule-frequency').value,
retention_days: parseInt(document.getElementById('retention-days').value)
};
fetch('/api/backup/schedule', {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify(formData)
})
.then(response => response.json())
.then(data => {
if (data.success) {
alert('✅ ' + data.message);
} else {
alert('❌ ' + data.message);
}
})
.catch(error => {
console.error('Error saving schedule:', error);
alert('❌ Failed to save schedule');
});
});
// Download backup function
function downloadBackup(filename) {
window.location.href = `/api/backup/download/${filename}`;
}
// Delete backup function
function deleteBackup(filename) {
if (confirm(`Are you sure you want to delete backup: ${filename}?`)) {
fetch(`/api/backup/delete/${filename}`, {
method: 'DELETE'
})
.then(response => response.json())
.then(data => {
if (data.success) {
alert('✅ ' + data.message);
loadBackupList();
} else {
alert('❌ ' + data.message);
}
})
.catch(error => {
console.error('Error deleting backup:', error);
alert('❌ Failed to delete backup');
});
}
}
// Load backup data on page load
if (document.getElementById('backup-list')) {
loadBackupSchedule();
loadBackupList();
}
</script>
{% endblock %}