Files
calibresync/templates/index.html
T
2026-05-10 18:02:06 +02:00

141 lines
4.6 KiB
HTML

{% 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/rescan" style="display:inline">
<button class="btn btn-secondary" {% if sync_running %}disabled{% endif %}>Rescan remote</button>
</form>
<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" {% if cache_info.count == 0 %}title="Run 'Rescan remote' first to populate the zip list"{% endif %}>Run Sync Now</button>
{% endif %}
</form>
{% if not sync_running %}
<form method="post" action="/sync/test" style="display:inline">
<button class="btn btn-secondary">Test (1 zip)</button>
</form>
{% endif %}
</div>
</div>
{% if batch_size > 0 %}
<p class="muted small" style="margin-bottom:1.5rem">Batch size: {{ batch_size }} zips per chunk — full sync processes all unprocessed files.</p>
{% endif %}
{% if request.query_params.get("started") %}
<div class="alert alert-success">Sync started — processing all unprocessed archives{% if batch_size > 0 %} in batches of {{ batch_size }}{% endif %}.</div>
{% endif %}
{% if request.query_params.get("test_started") %}
<div class="alert alert-success">Test sync started — processing 1 archive.</div>
{% endif %}
{% if request.query_params.get("rescan_started") %}
<div class="alert alert-success">Remote rescan started — this will take a few minutes. Check logs for progress.</div>
{% endif %}
{% if request.query_params.get("already_running") %}
<div class="alert alert-warning">A sync is already running.</div>
{% endif %}
<div class="cache-status">
{% if cache_info.count > 0 %}
<span class="muted small">Remote cache: <strong>{{ cache_info.count }}</strong> zip(s) &mdash; last scanned {{ cache_info.last_scan[:19] if cache_info.last_scan else "never" }} UTC</span>
{% else %}
<span class="muted small" style="color:var(--warning)">Remote cache empty &mdash; first sync will run a full scan (may take several minutes).</span>
{% endif %}
</div>
<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 %}