feat(config): stats vidéo + user 1000:1000 dans docker-compose

Admin stats : ajout video (count + size_bytes) dans /api/admin/stats.
ConfigPage : grille médias 3 colonnes (Photos / Audio / Vidéos).

docker-compose : backend et backend-worker tournent en user 1000:1000
pour que les fichiers écrits dans ./data/ appartiennent à l'utilisateur
hôte et non à root.

v0.5.6

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-05-25 16:44:31 +02:00
parent dd4ce6f52b
commit c72ca04fd2
5 changed files with 8 additions and 2 deletions
+2
View File
@@ -33,12 +33,14 @@ async def get_stats(session: AsyncSession = Depends(get_session)):
uploads = settings.upload_path
photos = _dir_stats(uploads / "images" / "originals") if (uploads / "images" / "originals").exists() else {"count": 0, "size_bytes": 0}
audio = _dir_stats(uploads / "audio") if (uploads / "audio").exists() else {"count": 0, "size_bytes": 0}
video = _dir_stats(uploads / "videos") if (uploads / "videos").exists() else {"count": 0, "size_bytes": 0}
return {
"db_size_bytes": db_size,
"media": {
"photos": photos,
"audio": audio,
"video": video,
},
"counts": {
"notes": notes_count,
+2
View File
@@ -25,6 +25,7 @@ services:
backend:
build: ./backend
user: "1000:1000"
environment:
DATABASE_URL: postgresql+asyncpg://homehub:homehub@db:5432/homehub
UPLOAD_DIR: /data/uploads
@@ -44,6 +45,7 @@ services:
backend-worker:
build: ./backend
user: "1000:1000"
command: arq app.workers.notes_worker.WorkerSettings
environment:
DATABASE_URL: postgresql+asyncpg://homehub:homehub@db:5432/homehub
+1 -1
View File
@@ -1,7 +1,7 @@
{
"name": "homehub-frontend",
"private": true,
"version": "0.5.5",
"version": "0.5.6",
"type": "module",
"scripts": {
"dev": "vite",
+1
View File
@@ -3,6 +3,7 @@ export interface AppStats {
media: {
photos: { count: number; size_bytes: number }
audio: { count: number; size_bytes: number }
video: { count: number; size_bytes: number }
}
counts: {
notes: number
+2 -1
View File
@@ -155,10 +155,11 @@ export default function ConfigPage() {
</div>
{/* Médias */}
<div style={{ display: 'grid', gridTemplateColumns: '1fr 1fr', gap: 8 }}>
<div style={{ display: 'grid', gridTemplateColumns: 'repeat(3, 1fr)', gap: 8 }}>
{[
{ icon: 'image', label: 'Photos', data: stats.media.photos },
{ icon: 'microphone', label: 'Audio', data: stats.media.audio },
{ icon: 'video', label: 'Vidéos', data: stats.media.video },
].map(item => (
<div key={item.label} style={{ background: 'var(--bg-4)', borderRadius: 8, padding: '8px 10px', display: 'flex', alignItems: 'center', gap: 8 }}>
<i className={`fa-solid fa-${item.icon}`} style={{ color: 'var(--info)', fontSize: 14, flexShrink: 0 }} />