feat: stats corbeille dans le tableau de bord

Nouvelle stat box cliquable (→ /trash) affichant le nombre de fichiers,
la taille totale et la date du plus ancien fichier en corbeille.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
Alpinux 2026-05-06 10:43:54 +02:00
parent b3af420d36
commit d2683a02e0
3 changed files with 34 additions and 0 deletions

View file

@ -279,6 +279,25 @@ def _trash_count() -> int:
if f.is_file() and not f.name.endswith(".trashinfo")) if f.is_file() and not f.name.endswith(".trashinfo"))
def _trash_stats() -> dict:
if not TRASH_ROOT.exists():
return {"files": 0, "size": 0, "oldest": None}
files, size, oldest = 0, 0, None
for f in TRASH_ROOT.rglob("*"):
if not f.is_file() or f.name.endswith(".trashinfo"):
continue
files += 1
size += f.stat().st_size
info = Path(str(f) + ".trashinfo")
try:
dt = datetime.fromisoformat(json.loads(info.read_text())["deleted_at"])
if oldest is None or dt < oldest:
oldest = dt
except Exception:
pass
return {"files": files, "size": size, "oldest": oldest}
def _folder_stats(path: Path) -> dict: def _folder_stats(path: Path) -> dict:
files, size = 0, 0 files, size = 0, 0
for f in path.rglob("*"): for f in path.rglob("*"):
@ -399,6 +418,7 @@ def dashboard():
folders=folders, folders=folders,
total_files=sum(v["files"] for v in folders.values()), total_files=sum(v["files"] for v in folders.values()),
total_size=sum(v["size"] for v in folders.values()), total_size=sum(v["size"] for v in folders.values()),
trash=_trash_stats(),
humansize=_humansize, humansize=_humansize,
) )

View file

@ -51,6 +51,11 @@ main { max-width: 1100px; margin: 2rem auto; padding: 0 1.5rem 3rem; display: fl
.stat-box { flex: 1; min-width: 160px; background: var(--blue-light); border-radius: 8px; padding: 1.2rem 1.5rem; } .stat-box { flex: 1; min-width: 160px; background: var(--blue-light); border-radius: 8px; padding: 1.2rem 1.5rem; }
.stat-box .label { font-size: .78rem; color: var(--muted); text-transform: uppercase; letter-spacing: .05em; margin-bottom: .4rem; } .stat-box .label { font-size: .78rem; color: var(--muted); text-transform: uppercase; letter-spacing: .05em; margin-bottom: .4rem; }
.stat-box .value { font-size: 1.9rem; font-weight: 700; color: var(--blue-dark); line-height: 1; } .stat-box .value { font-size: 1.9rem; font-weight: 700; color: var(--blue-dark); line-height: 1; }
.stat-box .stat-sub { font-size: .75rem; color: var(--muted); margin-top: .35rem; }
.stat-box--trash { background: #fef2f2; text-decoration: none; transition: box-shadow .15s; cursor: pointer; }
.stat-box--trash:hover { box-shadow: 0 4px 16px rgba(239,68,68,.18); text-decoration: none; }
.stat-box--trash .label { color: #b91c1c; }
.stat-box--trash .value { color: #991b1b; }
/* ── Grille de dossiers ───────────────────────────────────────── */ /* ── Grille de dossiers ───────────────────────────────────────── */
.folder-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(190px, 1fr)); gap: 1rem; } .folder-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(190px, 1fr)); gap: 1rem; }

View file

@ -16,6 +16,15 @@
<div class="label">Dossiers</div> <div class="label">Dossiers</div>
<div class="value">{{ folders | length }}</div> <div class="value">{{ folders | length }}</div>
</div> </div>
<a href="{{ url_for('trash_list') }}" class="stat-box stat-box--trash">
<div class="label">Corbeille</div>
<div class="value">{{ trash.files }}</div>
<div class="stat-sub">{{ humansize(trash.size) }}
{% if trash.oldest %}
· depuis le {{ trash.oldest.strftime('%d/%m/%Y') }}
{% endif %}
</div>
</a>
</div> </div>
<section class="card"> <section class="card">