From bf2f01c4c6efb050c86b86c182ce140bb572ff87 Mon Sep 17 00:00:00 2001 From: marwin Date: Mon, 16 Mar 2026 20:16:30 +0100 Subject: [PATCH] Add history delete button and Truckers FM station --- radio/urls.py | 1 + radio/views.py | 15 ++++++++++++++- static/css/app.css | 11 +++++++++++ static/js/app.js | 13 +++++++++++++ templates/radio/player.html | 6 ++++-- 5 files changed, 43 insertions(+), 3 deletions(-) diff --git a/radio/urls.py b/radio/urls.py index f5d9b98..65ecb01 100644 --- a/radio/urls.py +++ b/radio/urls.py @@ -10,6 +10,7 @@ urlpatterns = [ path('radio/remove//', views.remove_station, name='remove_station'), path('radio/favorite//', views.toggle_favorite, name='toggle_favorite'), path('radio/history/', views.history_json, name='history_json'), + path('radio/history//delete/', views.delete_history_entry, name='delete_history_entry'), path('radio/play/start/', views.start_play, name='start_play'), path('radio/play/stop/', views.stop_play, name='stop_play'), path('radio/recommendations/', views.recommendations, name='recommendations'), diff --git a/radio/views.py b/radio/views.py index aba0f7e..20e7744 100644 --- a/radio/views.py +++ b/radio/views.py @@ -37,7 +37,7 @@ def index(request): ) history = list( request.user.track_history.values( - 'station_name', 'track', 'played_at', 'scrobbled' + 'id', 'station_name', 'track', 'played_at', 'scrobbled' )[:50] ) # Convert datetime to ISO string for JSON serialisation in template @@ -383,6 +383,19 @@ def recommendations(request): # History JSON # --------------------------------------------------------------------------- +@csrf_exempt +@require_http_methods(['POST']) +def delete_history_entry(request, pk): + if not request.user.is_authenticated: + return JsonResponse({'error': 'authentication required'}, status=401) + try: + entry = TrackHistory.objects.get(pk=pk, user=request.user) + entry.delete() + return JsonResponse({'ok': True}) + except TrackHistory.DoesNotExist: + return JsonResponse({'error': 'not found'}, status=404) + + def history_json(request): if not request.user.is_authenticated: return JsonResponse({'error': 'authentication required'}, status=401) diff --git a/static/css/app.css b/static/css/app.css index 83abf35..0765b89 100644 --- a/static/css/app.css +++ b/static/css/app.css @@ -895,3 +895,14 @@ body.dnd-mode .timer-display { font-size: 0.85rem; color: var(--fg); } + +.btn-delete-history { + background: none; + border: none; + color: var(--muted, #888); + cursor: pointer; + font-size: 0.75rem; + padding: 0 4px; + opacity: 0.5; +} +.btn-delete-history:hover { opacity: 1; color: #e55; } diff --git a/static/js/app.js b/static/js/app.js index e9aac47..d377204 100644 --- a/static/js/app.js +++ b/static/js/app.js @@ -257,10 +257,23 @@ function addHistoryRow(stationName, track) { ${escapeHtml(stationName)} ${escapeHtml(track)} + `; tbody.insertBefore(tr, tbody.firstChild); } +async function deleteHistoryEntry(id, btn) { + const tr = btn.closest('tr'); + if (!id) { tr.remove(); return; } + try { + const res = await fetch(`/radio/history/${id}/delete/`, { + method: 'POST', + headers: {'X-CSRFToken': getCsrfToken()}, + }); + if (res.ok) tr.remove(); + } catch (e) {} +} + // --------------------------------------------------------------------------- // Affiliate links // --------------------------------------------------------------------------- diff --git a/templates/radio/player.html b/templates/radio/player.html index fe65ac4..b71cebd 100644 --- a/templates/radio/player.html +++ b/templates/radio/player.html @@ -144,18 +144,20 @@ Station Track ♬ + {% for entry in history %} - + {{ entry.played_at|slice:":16"|cut:"T" }} {{ entry.station_name }} {{ entry.track }} {% if entry.scrobbled %}{% endif %} + {% empty %} - No history yet. + No history yet. {% endfor %}