250 lines
10 KiB
HTML
250 lines
10 KiB
HTML
{% extends 'base.html' %}
|
|
|
|
{% block title %}Database Management - Manufacturing App{% endblock %}
|
|
|
|
{% block content %}
|
|
<div class="container-fluid">
|
|
<!-- Page header -->
|
|
<div class="d-flex justify-content-between flex-wrap flex-md-nowrap align-items-center pt-3 pb-2 mb-3 border-bottom">
|
|
<h1 class="h2">
|
|
<i class="bi bi-database me-2"></i>
|
|
Database Management
|
|
</h1>
|
|
</div>
|
|
|
|
<div class="row">
|
|
<!-- Database Information -->
|
|
<div class="col-lg-4 mb-4">
|
|
<div class="card">
|
|
<div class="card-header">
|
|
<h6 class="m-0 font-weight-bold text-primary">
|
|
<i class="bi bi-info-circle me-2"></i>
|
|
Database Information
|
|
</h6>
|
|
</div>
|
|
<div class="card-body">
|
|
<div class="mb-3">
|
|
<strong>Database Engine:</strong>
|
|
<span class="badge bg-primary ms-2">SQLite</span>
|
|
</div>
|
|
<div class="mb-3">
|
|
<strong>Database File:</strong>
|
|
<code class="ms-2">db.sqlite3</code>
|
|
</div>
|
|
<div class="mb-3">
|
|
<strong>Location:</strong>
|
|
<code class="ms-2">Project Root</code>
|
|
</div>
|
|
<div class="mb-3">
|
|
<strong>Size:</strong>
|
|
<span class="ms-2">{{ db_size|default:"Calculating..." }}</span>
|
|
</div>
|
|
<div class="mb-3">
|
|
<strong>Last Modified:</strong>
|
|
<span class="ms-2">{{ db_modified|default:"Unknown" }}</span>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Backup Database -->
|
|
<div class="col-lg-4 mb-4">
|
|
<div class="card">
|
|
<div class="card-header">
|
|
<h6 class="m-0 font-weight-bold text-success">
|
|
<i class="bi bi-download me-2"></i>
|
|
Backup Database
|
|
</h6>
|
|
</div>
|
|
<div class="card-body">
|
|
<p class="text-muted">
|
|
Create a backup of the current database. The backup will be saved in the 'backups' folder.
|
|
</p>
|
|
<form method="post" action="{% url 'core:backup_database' %}">
|
|
{% csrf_token %}
|
|
<button type="submit" class="btn btn-success w-100">
|
|
<i class="bi bi-download me-2"></i>
|
|
Create Backup
|
|
</button>
|
|
</form>
|
|
<small class="text-muted">
|
|
Backup files are saved with timestamps for easy identification.
|
|
</small>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Duplicate Database -->
|
|
<div class="col-lg-4 mb-4">
|
|
<div class="card">
|
|
<div class="card-header">
|
|
<h6 class="m-0 font-weight-bold text-info">
|
|
<i class="bi bi-files me-2"></i>
|
|
Duplicate Database
|
|
</h6>
|
|
</div>
|
|
<div class="card-body">
|
|
<p class="text-muted">
|
|
Create a duplicate copy of the current database for testing or development purposes.
|
|
</p>
|
|
<form method="post" action="{% url 'core:duplicate_database' %}">
|
|
{% csrf_token %}
|
|
<button type="submit" class="btn btn-info w-100">
|
|
<i class="bi bi-files me-2"></i>
|
|
Duplicate Database
|
|
</button>
|
|
</form>
|
|
<small class="text-muted">
|
|
Duplicate files are saved in the 'backups' folder.
|
|
</small>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Restore Database -->
|
|
<div class="row">
|
|
<div class="col-lg-8">
|
|
<div class="card">
|
|
<div class="card-header">
|
|
<h6 class="m-0 font-weight-bold text-warning">
|
|
<i class="bi bi-upload me-2"></i>
|
|
Restore Database
|
|
</h6>
|
|
</div>
|
|
<div class="card-body">
|
|
<div class="alert alert-warning">
|
|
<i class="bi bi-exclamation-triangle me-2"></i>
|
|
<strong>Warning:</strong> Restoring a database will overwrite the current database.
|
|
A safety backup of the current database will be created automatically before restoration.
|
|
</div>
|
|
|
|
<form method="post" action="{% url 'core:restore_database' %}" enctype="multipart/form-data">
|
|
{% csrf_token %}
|
|
<div class="mb-3">
|
|
<label for="backup_file" class="form-label">Select Backup File</label>
|
|
<input type="file" class="form-control" id="backup_file" name="backup_file"
|
|
accept=".sqlite3,.db" required>
|
|
<div class="form-text">
|
|
Only SQLite database files (.sqlite3, .db) are supported.
|
|
</div>
|
|
</div>
|
|
|
|
<div class="mb-3">
|
|
<div class="form-check">
|
|
<input class="form-check-input" type="checkbox" id="confirm_restore" required>
|
|
<label class="form-check-label" for="confirm_restore">
|
|
I understand that this will overwrite the current database
|
|
</label>
|
|
</div>
|
|
</div>
|
|
|
|
<button type="submit" class="btn btn-warning" id="restore_btn" disabled>
|
|
<i class="bi bi-upload me-2"></i>
|
|
Restore Database
|
|
</button>
|
|
</form>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Available Backups -->
|
|
<div class="col-lg-4">
|
|
<div class="card">
|
|
<div class="card-header">
|
|
<h6 class="m-0 font-weight-bold text-primary">
|
|
<i class="bi bi-folder me-2"></i>
|
|
Available Backups
|
|
</h6>
|
|
</div>
|
|
<div class="card-body">
|
|
{% if available_backups %}
|
|
<div class="list-group list-group-flush">
|
|
{% for backup in available_backups %}
|
|
<div class="list-group-item d-flex justify-content-between align-items-center">
|
|
<div>
|
|
<small class="text-muted">{{ backup.name }}</small>
|
|
<br>
|
|
<small class="text-muted">{{ backup.size }}</small>
|
|
</div>
|
|
<small class="text-muted">{{ backup.modified }}</small>
|
|
</div>
|
|
{% endfor %}
|
|
</div>
|
|
{% else %}
|
|
<p class="text-muted">No backup files found.</p>
|
|
{% endif %}
|
|
|
|
<div class="mt-3">
|
|
<a href="#" class="btn btn-outline-primary btn-sm w-100">
|
|
<i class="bi bi-folder-open me-2"></i>
|
|
Open Backups Folder
|
|
</a>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Database Statistics -->
|
|
<div class="row mt-4">
|
|
<div class="col-12">
|
|
<div class="card">
|
|
<div class="card-header">
|
|
<h6 class="m-0 font-weight-bold text-primary">
|
|
<i class="bi bi-bar-chart me-2"></i>
|
|
Database Statistics
|
|
</h6>
|
|
</div>
|
|
<div class="card-body">
|
|
<div class="row text-center">
|
|
<div class="col-md-3 mb-3">
|
|
<h4 class="text-primary">{{ total_users|default:"0" }}</h4>
|
|
<p class="text-muted">Total Users</p>
|
|
</div>
|
|
<div class="col-md-3 mb-3">
|
|
<h4 class="text-success">{{ total_products|default:"0" }}</h4>
|
|
<p class="text-muted">Total Products</p>
|
|
</div>
|
|
<div class="col-md-3 mb-3">
|
|
<h4 class="text-info">{{ total_orders|default:"0" }}</h4>
|
|
<p class="text-muted">Total Orders</p>
|
|
</div>
|
|
<div class="col-md-3 mb-3">
|
|
<h4 class="text-warning">{{ total_customers|default:"0" }}</h4>
|
|
<p class="text-muted">Total Customers</p>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
{% endblock %}
|
|
|
|
{% block extra_js %}
|
|
<script>
|
|
// Enable/disable restore button based on checkbox
|
|
document.getElementById('confirm_restore').addEventListener('change', function() {
|
|
document.getElementById('restore_btn').disabled = !this.checked;
|
|
});
|
|
|
|
// File input validation
|
|
document.getElementById('backup_file').addEventListener('change', function() {
|
|
const file = this.files[0];
|
|
if (file) {
|
|
const allowedTypes = ['application/x-sqlite3', 'application/vnd.sqlite3', 'application/octet-stream'];
|
|
const allowedExtensions = ['.sqlite3', '.db'];
|
|
|
|
const isValidType = allowedTypes.includes(file.type) ||
|
|
allowedExtensions.some(ext => file.name.toLowerCase().endsWith(ext));
|
|
|
|
if (!isValidType) {
|
|
alert('Please select a valid SQLite database file (.sqlite3 or .db)');
|
|
this.value = '';
|
|
}
|
|
}
|
|
});
|
|
</script>
|
|
{% endblock %}
|