Initial commit

This commit is contained in:
2026-05-09 18:41:03 +02:00
commit d384f1f896
18 changed files with 1339 additions and 0 deletions
+115
View File
@@ -0,0 +1,115 @@
{% extends "base.html" %}
{% block title %}Dashboard — CalibreSync{% endblock %}
{% block content %}
<div class="page-header">
<h1>Dashboard</h1>
<div class="header-actions">
{% if interval > 0 %}
<span class="schedule-badge">
Auto every {{ interval }}m
{% if next_run %} &mdash; next: {{ next_run }}{% endif %}
</span>
{% endif %}
<form method="post" action="/sync" style="display:inline">
{% if sync_running %}
<button class="btn btn-disabled" disabled>Sync running…</button>
{% else %}
<button class="btn btn-primary">Run Sync Now</button>
{% endif %}
</form>
</div>
</div>
{% if request.query_params.get("started") %}
<div class="alert alert-success">Sync started in background.</div>
{% endif %}
{% if request.query_params.get("already_running") %}
<div class="alert alert-warning">A sync is already running.</div>
{% endif %}
<div class="stats-grid">
<div class="stat-card">
<div class="stat-value">{{ stats.total_zips }}</div>
<div class="stat-label">Zip archives processed</div>
</div>
<div class="stat-card">
<div class="stat-value">{{ stats.uploaded }}</div>
<div class="stat-label">Books uploaded</div>
</div>
<div class="stat-card">
<div class="stat-value">{{ stats.skipped }}</div>
<div class="stat-label">Duplicates skipped</div>
</div>
<div class="stat-card">
<div class="stat-value">{{ stats.total_books }}</div>
<div class="stat-label">Total book records</div>
</div>
</div>
<h2>Recent sync runs</h2>
{% if runs %}
<table>
<thead>
<tr>
<th>Started</th>
<th>Finished</th>
<th>Status</th>
<th>New zips</th>
<th>Uploaded</th>
<th>Skipped</th>
<th>Errors</th>
</tr>
</thead>
<tbody>
{% for r in runs %}
<tr>
<td>{{ r.started_at[:19].replace("T"," ") }}</td>
<td>{{ r.finished_at[:19].replace("T"," ") if r.finished_at else "—" }}</td>
<td><span class="badge badge-{{ r.status }}">{{ r.status }}</span></td>
<td>{{ r.zips_new }}</td>
<td>{{ r.books_uploaded }}</td>
<td>{{ r.books_skipped }}</td>
<td>{{ r.books_errored }}</td>
</tr>
{% endfor %}
</tbody>
</table>
{% else %}
<p class="muted">No sync runs yet. Click "Run Sync" to start.</p>
{% endif %}
<h2>Recent zip archives</h2>
{% if zips %}
<table>
<thead>
<tr>
<th>Remote path</th>
<th>Size</th>
<th>Processed</th>
<th>Status</th>
<th>Error</th>
</tr>
</thead>
<tbody>
{% for z in zips %}
<tr>
<td class="mono">{{ z.remote_path }}</td>
<td>{{ (z.file_size / 1048576) | round(1) }} MB</td>
<td>{{ z.processed_at[:19].replace("T"," ") if z.processed_at else "—" }}</td>
<td><span class="badge badge-{{ z.status }}">{{ z.status }}</span></td>
<td class="muted small">{{ z.error_msg or "" }}</td>
</tr>
{% endfor %}
</tbody>
</table>
{% else %}
<p class="muted">No zip archives processed yet.</p>
{% endif %}
{% if sync_running %}
<script>
setTimeout(() => location.reload(), 5000);
</script>
{% endif %}
{% endblock %}