Incremental forward upgrades of the database

This commit is contained in:
2025-01-20 17:43:15 +01:00
parent c6e5a6a2d9
commit 5e99371b39
15 changed files with 298 additions and 104 deletions
+2
View File
@@ -18,6 +18,8 @@
{% include 'admin/database/drop.html' %}
{% elif import_database %}
{% include 'admin/database/import.html' %}
{% elif upgrade_database %}
{% include 'admin/database/upgrade.html' %}
{% else %}
{% include 'admin/logout.html' %}
{% include 'admin/instructions.html' %}
+19 -33
View File
@@ -2,41 +2,30 @@
{{ accordion.header('Database', 'database', 'admin', expanded=open_database, icon='database-2-line') }}
<h5 class="border-bottom">Status</h5>
{% if exception %}<div class="alert alert-danger" role="alert">An exception occured while loading this page: {{ exception }}</div>{% endif %}
{% if error %}<div class="alert alert-danger" role="alert"><strong>Error:</strong> {{ error }}.</div>{% endif %}
{% if not is_init %}
{% if database_exception %}<div class="alert alert-danger" role="alert">An exception occured while loading this page: {{ database_exception }}</div>{% endif %}
{% if database_error %}<div class="alert alert-danger" role="alert"><strong>Error:</strong> {{ database_error }}.</div>{% endif %}
{% if database_needs_upgrade %}
<div class="alert alert-warning" role="alert">
<p>The database file is: <code>{{ config['DATABASE_PATH'] }}</code>. The database is not initialized.</p>
<p>Your database needs to be upgraded.</p>
<hr>
<form action="{{ url_for('admin.init_database') }}" method="post" class="text-end">
<button type="submit" class="btn btn-warning"><i class="ri-reset-right-fill"></i> Initialize the database</button>
</form>
</div>
{% else %}
{% if count_none %}
<div class="alert alert-warning" role="alert">
<p>
Your <code>missing</code> table contains <code>"None"</code> entries (instead of <code>NULL</code>). <br>
This can lead to "phantom" missing parts appearing in your sets if you are coming from the original version of BrickTracker.
</p>
<hr>
<form action="{{ url_for('admin.init_database') }}" method="post" class="text-end">
<button type="submit" class="btn btn-warning"><i class="ri-capsule-line"></i> Apply the fix</button>
</form>
<div class="text-end">
<a href="{{ url_for('admin.upgrade_database') }}" class="btn btn-warning" role="button"><i class="ri-arrow-up-double-line"></i> Upgrade the database</a>
</div>
{% endif %}
<p>The database file is: <code>{{ config['DATABASE_PATH'] }}</code>. <i class="ri-checkbox-circle-line"></i> The database is initialized.</p>
<p>
<a href="{{ url_for('admin.download_database') }}" class="btn btn-primary" role="button"><i class="ri-download-line"></i> Download the database file</a>
</p>
</div>
{% endif %}
<p>The database file is: <code>{{ config['DATABASE_PATH'] }}</code> at version <span class="badge rounded-pill text-bg-light border fw-normal"><i class="ri-hashtag"></i>{{ database_version }}</span></p>
<p>
<a href="{{ url_for('admin.download_database') }}" class="btn btn-primary" role="button"><i class="ri-download-line"></i> Download the database file</a>
</p>
{% if database_counters %}
<h5 class="border-bottom">Records</h5>
<div class="d-flex justify-content-start">
<ul class="list-group">
{% for counter in counters %}
{% if not (loop.index % 5) %}
</ul>
<ul class="list-group">
{% endif %}
<ul class="list-group me-2">
{% for counter in database_counters %}
{% if not (loop.index % 5) %}
</ul>
<ul class="list-group">
{% endif %}
<li class="list-group-item d-flex justify-content-between align-items-start">
<span><i class="ri-{{ counter.icon }}"></i> {{ counter.name }}</span> <span class="badge text-bg-primary rounded-pill ms-2">{{ counter.count }}</span>
</li>
@@ -49,9 +38,6 @@
{{ accordion.header('Database danger zone', 'database-danger', 'admin', danger=true, class='text-end') }}
{% if error %}<div class="alert alert-danger text-start" role="alert"><strong>Error:</strong> {{ error }}.</div>{% endif %}
<a href="{{ url_for('admin.import_database') }}" class="btn btn-warning" role="button"><i class="ri-upload-line"></i> Import a database file</a>
<form action="{{ url_for('admin.init_database') }}" method="post" class="d-inline">
<button type="submit" class="btn btn-warning"><i class="ri-reset-right-fill"></i> Initialize the database (only missing tables)</button>
</form>
<a href="{{ url_for('admin.drop_database') }}" class="btn btn-danger" role="button"><i class="ri-close-line"></i> Drop the database</a>
<a href="{{ url_for('admin.delete_database') }}" class="btn btn-danger" role="button"><i class="ri-delete-bin-2-line"></i> Delete the database file</a>
{{ accordion.footer() }}
+29
View File
@@ -0,0 +1,29 @@
{% import 'macro/accordion.html' as accordion %}
{{ accordion.header('Database', 'database', 'admin', expanded=true, icon='database-2-line') }}
<form action="{{ url_for('admin.do_upgrade_database') }}" method="post">
{% if error %}<div class="alert alert-danger text-start" role="alert"><strong>Error:</strong> {{ error }}.</div>{% endif %}
<div class="alert alert-warning text-center" role="alert">
You are about to <strong>upgrade your database file</strong>. This action is irreversible.<br>
The process shold be lossless, but just to be sure, grab a copy of your database before proceeding.<br>
</div>
<h5 class="border-bottom">Upgrades</h5>
<ul>
{% for migration in migrations %}
<li>
<span class="badge rounded-pill text-bg-light border fw-normal me-2"><i class="ri-hashtag"></i>{{ migration.version }}</span>
{% if migration.get_description() %}
<code>{{ migration.get_description() }}</code>
{% else %}
<span class="badge rounded-pill text-bg-secondary fst-italic">No description</span>
{% endif %}
</li>
{% endfor %}
</ul>
<div class="text-end">
<a class="btn btn-danger" href="{{ url_for('admin.admin') }}" role="button"><i class="ri-arrow-left-long-line"></i> Back to the admin</a>
<a href="{{ url_for('admin.download_database') }}" class="btn btn-primary" role="button"><i class="ri-download-line"></i> Download the database file</a>
<button type="submit" class="btn btn-warning"><i class="ri-arrow-up-double-line"></i> Upgrade the database</button>
</div>
</form>
{{ accordion.footer() }}