admin: add Total imported and Last sync columns to Garmin sync table
Matches the Strava sync table layout. Accumulates total_imported in garmin_sync.json state on each sync run; admin API exposes last_sync_at and total_imported from that file.
This commit is contained in:
@@ -174,6 +174,7 @@ def garmin_sync_iter(
|
||||
|
||||
# ── Persist sync state ─────────────────────────────────────────────────────
|
||||
state["last_sync_at"] = datetime.now(timezone.utc).strftime("%Y-%m-%d")
|
||||
state["total_imported"] = state.get("total_imported", 0) + imported
|
||||
_save_sync_state(user_dir, state)
|
||||
|
||||
yield {
|
||||
|
||||
@@ -607,6 +607,17 @@ async def admin_garmin_sync_status(
|
||||
user_dir = cf.parent
|
||||
handle = user_dir.name
|
||||
|
||||
last_sync: str | None = None
|
||||
total_imported = 0
|
||||
sync_path = user_dir / "garmin_sync.json"
|
||||
if sync_path.exists():
|
||||
try:
|
||||
sc = json.loads(sync_path.read_text(encoding="utf-8"))
|
||||
last_sync = sc.get("last_sync_at")
|
||||
total_imported = sc.get("total_imported", 0)
|
||||
except (OSError, json.JSONDecodeError):
|
||||
pass
|
||||
|
||||
run_status: str | None = None
|
||||
run_imported = 0
|
||||
run_errors = 0
|
||||
@@ -626,6 +637,8 @@ async def admin_garmin_sync_status(
|
||||
|
||||
users.append({
|
||||
"handle": handle,
|
||||
"last_sync": last_sync,
|
||||
"total_imported": total_imported,
|
||||
"run_status": run_status,
|
||||
"run_imported": run_imported,
|
||||
"run_errors": run_errors,
|
||||
|
||||
@@ -67,13 +67,14 @@ import Base from '../../layouts/Base.astro';
|
||||
<thead>
|
||||
<tr class="text-left text-zinc-500 text-xs border-b border-zinc-800">
|
||||
<th class="px-4 py-2 font-medium">Handle</th>
|
||||
<th class="px-4 py-2 font-medium text-right">Imported (last run)</th>
|
||||
<th class="px-4 py-2 font-medium text-right">Total imported</th>
|
||||
<th class="px-4 py-2 font-medium">Last sync</th>
|
||||
<th class="px-4 py-2 font-medium">Last run</th>
|
||||
<th class="px-4 py-2 font-medium">Status</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody id="garmin-sync-list">
|
||||
<tr><td colspan="4" class="px-4 py-6 text-zinc-500 text-center">Loading…</td></tr>
|
||||
<tr><td colspan="5" class="px-4 py-6 text-zinc-500 text-center">Loading…</td></tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
@@ -662,7 +663,7 @@ import Base from '../../layouts/Base.astro';
|
||||
try {
|
||||
const r = await fetch('/api/admin/garmin-sync', { credentials: 'include' });
|
||||
if (!r.ok) {
|
||||
garminTbody.innerHTML = `<tr><td colspan="4" class="px-4 py-4 text-red-400 text-center">Error ${r.status}</td></tr>`;
|
||||
garminTbody.innerHTML = `<tr><td colspan="5" class="px-4 py-4 text-red-400 text-center">Error ${r.status}</td></tr>`;
|
||||
return;
|
||||
}
|
||||
const { running, users } = await r.json();
|
||||
@@ -682,19 +683,20 @@ import Base from '../../layouts/Base.astro';
|
||||
}
|
||||
|
||||
if (!users.length) {
|
||||
garminTbody.innerHTML = '<tr><td colspan="4" class="px-4 py-6 text-zinc-500 text-center">No users with Garmin connected.</td></tr>';
|
||||
garminTbody.innerHTML = '<tr><td colspan="5" class="px-4 py-6 text-zinc-500 text-center">No users with Garmin connected.</td></tr>';
|
||||
return;
|
||||
}
|
||||
|
||||
garminTbody.innerHTML = users.map((u: any) => `
|
||||
<tr class="border-b border-zinc-800/50">
|
||||
<td class="px-4 py-3 text-white font-mono text-xs">@${u.handle}</td>
|
||||
<td class="px-4 py-3 text-right text-zinc-300 tabular-nums">${u.run_imported ?? '—'}</td>
|
||||
<td class="px-4 py-3 text-right text-zinc-300 tabular-nums">${u.total_imported}</td>
|
||||
<td class="px-4 py-3 text-zinc-400 text-xs">${fmtDate(u.last_sync)}</td>
|
||||
<td class="px-4 py-3 text-zinc-400 text-xs">${fmtDate(u.last_run)}</td>
|
||||
<td class="px-4 py-3">${garminStatusBadge(u.run_status, u.run_error_message)}</td>
|
||||
</tr>`).join('');
|
||||
} catch (err) {
|
||||
garminTbody.innerHTML = `<tr><td colspan="4" class="px-4 py-4 text-red-400 text-center">${String(err)}</td></tr>`;
|
||||
garminTbody.innerHTML = `<tr><td colspan="5" class="px-4 py-4 text-red-400 text-center">${String(err)}</td></tr>`;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user