]> littlesong.place Git - littlesongplace.git/commitdiff
Add to playlist without refreshing page
authorChris Fulljames <christianfulljames@gmail.com>
Sun, 16 Mar 2025 20:09:26 +0000 (16:09 -0400)
committerChris Fulljames <christianfulljames@gmail.com>
Sun, 16 Mar 2025 20:09:26 +0000 (16:09 -0400)
main.py
static/nav.js
static/styles.css
templates/base.html
templates/news.html
templates/song-macros.html
test/test_offline.py
todo.txt

diff --git a/main.py b/main.py
index 6103b4debc7481d6bf4f6d025313100653727f00..4e71aa011c4963e1248eb970370bc07e6fcef36b 100644 (file)
--- a/main.py
+++ b/main.py
@@ -817,7 +817,7 @@ def append_to_playlist():
 
     flash_and_log(f"Added '{song_data['title']}' to {plist_data['name']}", "success")
 
-    return redirect(request.referrer)
+    return {"status": "success", "messages": get_flashed_messages()}
 
 @app.post("/edit-playlist/<int:playlistid>")
 def edit_playlist_post(playlistid):
index 4926f83aeb119d47bf77878bd288cf1c44f3825a..f2998a8057a2a29e9cfaa41d49c88bf500a90e94 100644 (file)
@@ -67,19 +67,49 @@ function urlIsOnSameSite(targetUrl) {
     return targetUrl.origin === currentUrl.origin;
 }
 
+var m_messageBoxTimeout;
+
 async function handleAjaxResponse(response) {
     if (response.status != 200) {
         // Got an error; redirect to the error page
         window.location.href = response.url;
     }
-    // Update URL in browser window
-    var url = new URL(response.url);
 
-    // Get page content from response
-    var text = await response.text();
-    window.history.pushState(text, "", url);
+    if (response.headers.get("content-type") === "application/json")
+    {
+        // JSON response - show message popup
+
+        var data = await response.json();
+        var messageBox = document.getElementById("message-box");
+        messageBox.textContent = data.messages[0];
+
+        if (data.status === "success")
+        {
+            messageBox.style["border-color"] = "var(--blue)";
+        }
+        else
+        {
+            messageBox.style["border-color"] = "red";
+        }
+
+        // Unhide message box for 5 seconds
+        clearTimeout(m_messageBoxTimeout);
+        messageBox.hidden = false;
+        m_messageBoxTimeout = setTimeout(() => {messageBox.hidden = true;}, 5000);
+    }
+    else
+    {
+        // HTML response
+
+        // Update URL in browser window
+        var url = new URL(response.url);
 
-    updatePageState(text);
+        // Get page content from response
+        var text = await response.text();
+        window.history.pushState(text, "", url);
+
+        updatePageState(text);
+    }
 }
 
 // Populate page state from history stack when user navigates back
index b3006ae538df8bc1297f79af03e5b2fec5250cd5..12bc5cf382f5bd11b5f93f2f99cda419835f6ee7 100644 (file)
@@ -94,6 +94,16 @@ div.page-header {
     margin: 20px;
 }
 
+#message-box {
+    box-sizing: border-box;
+    margin: 10px;
+    border-width: 3px;
+    border-radius: 10px;
+    border-style: solid;
+    padding: 10px;
+    background-color: var(--yellow);
+}
+
 .title-image {
     image-rendering: pixelated;
     width: 512px;
index 667651afd0f92e1f4dc1a99c6986f60d3b337d1e..0def43351deef406ed9a86906885b81645bf5a16 100644 (file)
@@ -5,7 +5,7 @@
         <link rel="stylesheet" href="/static/styles.css?v=2"/>
         <link rel="icon" type="image/x-icon" href="/static/lsp_notes.png?v=1"/>
         <script src="/static/player.js?v=1"></script>
-        <script src="/static/nav.js?v=1"></script>
+        <script src="/static/nav.js?v=2"></script>
         <meta name="viewport" content="width=device-width, initial-scale=1">
 
         <!-- Include coloris library for color picker -->
         <!-- Padding to prevent player from obscuring content -->
         <div id="scroll-padding"></div>
 
-        <!-- Song Player -->
         <div class="player-container" id="player-container">
+            <!-- Message Box -->
+            <div id="message-box" hidden></div>
+
+            <!-- Song Player -->
             <div class="player" id="player" hidden>
                 <div class="player-info">
                     <img id="player-pfp" class="small-pfp" src="" onerror="this.style.display = 'none'">
index 59e22b67fa1cee7ba01e94dbe9d22a206d3443eb..db02cba300601c284984ff3e02faf22ec5cd0943 100644 (file)
@@ -6,6 +6,13 @@
 
 <h1>Site News</h1>
 
+<h2>??</h2>
+<ul>
+    <li>Adding a song to a playlist no longer refreshes the page</li>
+    <li>Fixed a bug where scroll position was maintained after clicking a link</li>
+</ul>
+
+
 <h2>2025-03-01 - Increased Entropy</h2>
 Normally programming is about bringing order to chaos, but this week I've
 added chaos to your song order.  There's a new Random page that will randomly
index 65bd0e6bfa8f2363c65c0165cf86a679e4bc3462..c71b5d9b0f49cc0c1b74ebb3bd8313fb220d7d5d 100644 (file)
@@ -35,7 +35,7 @@
     <div class="song-playlist-controls">
         <form action="/append-to-playlist" method="post">
             <input type="hidden" name="songid" value="{{ song.songid }}" id="playlist-selector-songid"/>
-            <select name="playlistid" onchange="this.closest('form').requestSubmit()">
+            <select name="playlistid" onchange="this.closest('form').requestSubmit(); setTimeout(() => {this.selectedIndex = 0}, 0)">
                 <option value="-1">Add to Playlist...</option>
                 {% for plist in current_user_playlists -%}
                 <option value="{{ plist.playlistid }}">{{ plist['name'] }}</option>
index 2260fb087b33c6fd94a8ead84926fe296aaeeae7..2eec7bdfa27c0ef722f30816b4578eb034908184 100644 (file)
@@ -1041,9 +1041,10 @@ def _create_user_song_and_playlist(client, playlist_type="private"):
 
 def test_append_to_playlist(client):
     _create_user_song_and_playlist(client)
-    client.post("/append-to-playlist", data={"playlistid": "1", "songid": "1"})
-    response = client.get("/")
-    assert b"Added &#39;song title&#39; to my playlist" in response.data
+    response = client.post("/append-to-playlist", data={"playlistid": "1", "songid": "1"})
+    data = response.json
+    assert data["status"] == "success"
+    assert "Added 'song title' to my playlist" in data["messages"]
 
 def test_append_to_playlist_not_logged_in(client):
     _create_user_song_and_playlist(client)
index 6cd63ea543ab43591773e14f764355e2422be4dc..8c09e1ef67363bfa94bf93452969fd3358571ecf 100644 (file)
--- a/todo.txt
+++ b/todo.txt
@@ -1,12 +1,9 @@
 SOON
-- Add to playlist in background
-- Pinned profile playlists
 - Comments on profile(?), playlists
 - Player minimize button
 - Break up main.py, test_offline.py
 - Image support in comments, descriptions, bios, etc. (rich text?)
-- Profile background/banner image
-- Profile blocks(?)
+- Embeddable songs in bio
 - Song sorter for song lists
 - Song/User Search
 - Jam(s)(??)
@@ -20,3 +17,8 @@ MAYBE
 - Change password (require email?)
 - Autoplay toggle
 - Song downloads
+
+CANCEL?
+- Profile background/banner image (tile? scale? text backgrounds?)
+- Pinned profile playlists (where to put?  multiple playlists?)
+- Profile blocks(?)