From 84b5cd3d487562194335d01d830a316dfbf2a0c0 Mon Sep 17 00:00:00 2001 From: scheianu Date: Fri, 11 Sep 2026 14:28:49 +0300 Subject: [PATCH] Dashboard: add Playlist Overview card and compact the sidebar Restructure the dashboard into a two-column layout: a wide main column holding the new Playlist Overview card, and a narrow (220px) right sidebar with the compacted Quick Actions and Workflow Guide cards. The Overview card answers "which playlist should I add media to, and who will see it?" without opening each playlist. Per playlist it shows: - name, linked to that playlist's content manager - item count, total duration and current version - "N/M online" coverage, or a "no players" warning - one chip per assigned player, with an online/offline dot, linking to that player's manage page - an explicit empty state when no player is assigned Players with no playlist are surfaced in a separate warning, since they silently display nothing. main.py builds this in a fixed number of queries: players are fetched once and grouped by playlist_id, rather than calling Playlist.players per row (which would be one query per playlist). Layout notes: - minmax(0, 1fr) on the main column so long names cannot widen the grid - sidebar is sticky on tall screens and collapses below the main column under 900px, where the two small cards sit side by side - sidebar cards used the global .card hover lift; suppressed for these Also fixes a corrupted emoji (U+FFFD) in the System Status card. Verified at 1600/1200/950/850/600px: no overflow, no button label wrapping, and correct dark-mode colours. --- app/blueprints/main.py | 34 +++- app/templates/dashboard.html | 344 +++++++++++++++++++++++++++++------ 2 files changed, 324 insertions(+), 54 deletions(-) diff --git a/app/blueprints/main.py b/app/blueprints/main.py index d4fc239..322c377 100644 --- a/app/blueprints/main.py +++ b/app/blueprints/main.py @@ -34,14 +34,44 @@ def dashboard(): storage_mb = round(storage_mb / (1024 * 1024), 2) # Convert to MB server_logs = get_recent_logs(20) - + + # Per-playlist overview for the dashboard: which playlist holds what, and + # which players consume it. This answers "where should I add media / which + # playlist needs editing?" without opening each playlist. + # + # Players are fetched in a single query and grouped in Python rather than + # relying on Playlist.players per row, to avoid one query per playlist. + playlists = Playlist.query.order_by(Playlist.name).all() + players_by_playlist = {} + for player in Player.query.order_by(Player.name).all(): + if player.playlist_id is not None: + players_by_playlist.setdefault(player.playlist_id, []).append(player) + + playlist_overview = [] + for playlist in playlists: + assigned = players_by_playlist.get(playlist.id, []) + playlist_overview.append({ + 'playlist': playlist, + 'content_count': playlist.contents.count(), + 'total_duration': playlist.total_duration, + 'players': assigned, + 'player_count': len(assigned), + 'online_count': sum(1 for p in assigned if p.is_online), + }) + + # Players with no playlist produce no content on screen, so surface them. + unassigned_players = Player.query.filter(Player.playlist_id.is_(None))\ + .order_by(Player.name).all() + return render_template( 'dashboard.html', total_players=total_players, total_playlists=total_playlists, total_content=total_content, storage_mb=storage_mb, - recent_logs=server_logs + recent_logs=server_logs, + playlist_overview=playlist_overview, + unassigned_players=unassigned_players ) diff --git a/app/templates/dashboard.html b/app/templates/dashboard.html index 29be11b..e4840e7 100644 --- a/app/templates/dashboard.html +++ b/app/templates/dashboard.html @@ -43,73 +43,313 @@ -
-

Quick Actions

-
- - - Add Player - - - - Create Playlist - - - - Upload Media - - {% if current_user.is_admin %} - Admin Panel - {% endif %} -
-
+
+ +
+
+

+ + + Playlist Overview + + Manage +

+

+ Pick a playlist to add media to or edit. Players listed here are the devices + that will show it. +

-
-

- - Workflow Guide -

-
-
    -
  1. Create a Playlist - Group your content into themed collections
  2. -
  3. Upload Media - Add images, videos, or PDFs to your media library
  4. -
  5. Add Content to Playlist - Build your playlist with drag-and-drop ordering
  6. -
  7. Add Player - Register physical display devices
  8. -
  9. Assign Playlist - Connect players to their playlists
  10. -
  11. Players Auto-Download - Devices fetch and display content automatically
  12. -
+ {% if playlist_overview %} + {% for item in playlist_overview %} +
+
+
+ {{ item.playlist.name }} +
+ {{ item.content_count }} item{{ '' if item.content_count == 1 else 's' }} + · {{ item.total_duration }}s + · v{{ item.playlist.version }} + · + {% if item.player_count %} + + {{ item.online_count }}/{{ item.player_count }} online + + {% else %} + no players + {% endif %} +
+
+ Edit +
+ + {% if item.players %} +
+ {% for player in item.players %} + + + {{ player.name }} + + {% endfor %} +
+ {% else %} +

+ No players assigned — content here is not shown on any screen yet. + Assign a player → +

+ {% endif %} +
+ {% endfor %} + {% else %} +

+ No playlists yet. + Create your first playlist → +

+ {% endif %} + + {% if unassigned_players %} +
+ {{ unassigned_players | length }} player{{ '' if unassigned_players | length == 1 else 's' }} + not assigned to any playlist: + {% for player in unassigned_players %} + {{ player.name }}{{ ', ' if not loop.last else '' }} + {% endfor %} + — these will not display content until a playlist is assigned. +
+ {% endif %} +
+ + +
@@ -133,7 +373,7 @@ body.dark-mode .log-item {

System Status

✅ All systems operational

-

� Playlist-centric architecture active

+

📋 Playlist-centric architecture active

🔄 Groups removed - Streamlined workflow

⚡ DigiServer v2.0