]> littlesong.place Git - littlesongplace.git/commitdiff
Desktop attempt - kinda works?
authorChris Fulljames <christianfulljames@gmail.com>
Sun, 22 Jun 2025 21:39:41 +0000 (17:39 -0400)
committerChris Fulljames <christianfulljames@gmail.com>
Sun, 22 Jun 2025 21:39:41 +0000 (17:39 -0400)
src/littlesongplace/auth.py
src/littlesongplace/static/nav.js
src/littlesongplace/static/styles.css
src/littlesongplace/templates/base.html
src/littlesongplace/templates/index.html
src/littlesongplace/templates/song-macros.html
src/littlesongplace/users.py

index 174a5f273155ccda2f6339efec31c55bb7e282cc..1962960947379635065f8012c273c942eb04c9ba 100644 (file)
@@ -4,7 +4,7 @@ from datetime import datetime, timezone
 import bcrypt
 from flask import Blueprint, render_template, redirect, flash, g, request, current_app, session
 
-from . import comments, db
+from . import comments, db, users
 from .logutils import flash_and_log
 
 bp = Blueprint("auth", __name__)
@@ -108,10 +108,14 @@ def requires_login(f):
         if not "userid" in session:
             return redirect("/login")
 
-        g.userid = session["userid"]
-        g.username = session["username"]
-
         return f(*args, **kwargs)
 
     return _wrapper
 
+@bp.before_app_request
+def load_user():
+    if "userid" in session:
+        g.userid = session["userid"]
+        g.username = session["username"]
+        g.user = users.by_id(g.userid)
+
index 51421d39a3dbe9250fb9b49f190312a5a8141e90..57aed879be7b38cba0c1bacb8d84ecd5b527e64b 100644 (file)
@@ -31,10 +31,10 @@ document.addEventListener("DOMContentLoaded", async (e) => {
     var loggedIn = username ? true : false;
     document.querySelectorAll(".nav-logged-in").forEach((e) => {e.hidden = !loggedIn;});
     document.querySelectorAll(".nav-logged-out").forEach((e) => {e.hidden = loggedIn;});
-    if (loggedIn) {
-        document.getElementById("logged-in-status").innerText = `Signed in as ${username}`;
-        document.getElementById("my-profile").href = `/users/${username}`;
-    }
+    // if (loggedIn) {
+    //     document.getElementById("logged-in-status").innerText = `signed in as ${username}`;
+    //     document.getElementById("my-profile").href = `/users/${username}`;
+    // }
 
     // Add event handler to navbar links to hide menu on mobile
     document.querySelectorAll("#navbar a, #page-header div a").forEach((link) => {
@@ -166,9 +166,9 @@ function updatePageState(data) {
     data = parser.parseFromString(data, "text/html");
 
     // Update main body content
-    var newMainDiv = data.getElementById("main");
-    var oldMainDiv = document.getElementById("main");
-    document.body.replaceChild(newMainDiv, oldMainDiv);
+    var newOuterDiv = data.getElementById("outer");
+    var oldOuterDiv = document.getElementById("outer");
+    document.body.replaceChild(newOuterDiv, oldOuterDiv);
 
     // Update flashed messages
     var newFlashes = data.getElementById("flashes-container");
@@ -179,7 +179,7 @@ function updatePageState(data) {
     document.title = data.title;
 
     // Load inline scripts (DOMParser disables these by default)
-    var scripts = document.getElementById("main").getElementsByTagName("script");
+    var scripts = document.getElementById("outer").getElementsByTagName("script");
     for (const script of scripts) {
         var newScript = document.createElement("script");
         newScript.type = script.type;
index 930362dbc78140ca087a097a5366aa5bd268b7b2..c690c46bedec297cdad0e0459e77b33a4a5c9980 100644 (file)
@@ -42,7 +42,7 @@ body {
     color: var(--black);
     font-family: "Unageo", sans-serif;
     border-color: var(--purple);
-    max-width: 700px;
+    max-width: 1200px;
     margin: auto;
 }
 
@@ -147,12 +147,64 @@ select {
     padding: 8px;
 }
 
-div.main {
-    max-width: 700px;
-    margin: auto;
+#outer {
+    display: flex;
+    flex-direction: row;
+    align-items: flex-start;
+    gap: 20px;
+    margin-top: 20px;
+}
+
+#left {
+    flex-grow: 1;
+    display: flex;
+    flex-direction: column;
+    gap: 20px;
+}
+
+#main {
+    flex-grow: 2;
+    display: flex;
+    flex-direction: column;
+    gap: 20px;
+}
+
+#right {
+    flex-grow: 1;
+    display: flex;
+    flex-direction: column;
+    gap: 20px;
+}
+
+.page-section {
+    border: 1px solid var(--black);
+    box-shadow: 4px 4px 0px 0px var(--black);
+    border-radius: var(--radius);
     padding: 10px;
 }
 
+.page-section-header {
+    font-size: 26px;
+    font-family: "Mat Saleh", sans-serif;
+    /*border: 2px solid var(--purple);*/
+    background: var(--purple);
+    color: var(--yellow);
+    border-radius: var(--radius) var(--radius) 0px 0px;
+    text-align: center;
+    position: relative;
+    left: -10px;
+    top: -10px;
+    padding: 5px 0px;
+    width: calc(100% + 20px);
+}
+
+#user-actions {
+    display: flex;
+    gap: 10px;
+    justify-content: space-evenly;
+    margin: 10px 0px 0px 0px;
+}
+
 .flashes {
     border: 3px solid var(--blue);
     border-radius: var(--radius);
@@ -257,7 +309,6 @@ input[type=range]::-moz-range-thumb {
     background-color: var(--yellow);
     margin: 0px;
     padding: 5px;
-    box-sizing: border-box;
     width: 100%;
     height: 100%;
     top: 0px;
@@ -271,15 +322,27 @@ input[type=range]::-moz-range-thumb {
     justify-content: center;
     align-items: center;
     gap: 10px;
-    padding-bottom: 10px;
+    margin: 10px;
+}
+
+#site-title {
+    padding: 10px 20px;
+}
+
+#site-title a {
+    font-family: "Mat Saleh", sans-serif;
+    color: var(--purple);
+    font-size: 2em;
 }
 
 @media screen and (min-width: 480px) {
     #page-header {
         width: auto;
-        display: block;
+        display: flex;
+        align-items: center;
+        justify-content: space-between;
         position: static;
-        margin: 10px;
+        margin: 10px 0px;
         box-shadow: 5px 5px 0px 0px var(--black);
         border: 1px solid var(--black);
         border-radius: var(--radius);
@@ -506,29 +569,15 @@ div.song-main {
 div.song-info {
     font-family: "Unageo", sans-serif;
     display: flex;
-    flex-wrap: wrap;
-    flex-direction: row;
+    flex-direction: column;
+    align-items: flex-start;
     row-gap: 0px;
-    column-gap: 10px;
-    align-items: center;
     flex-grow: 1;
     margin: 5px 0px;
     min-width: 0;
     overflow: hidden;
 }
 
-/* Artist on separate line for mobile */
-@media screen and (max-width: 480px) {
-    div.song-info {
-        flex-direction: column;
-        align-items: flex-start;
-    }
-
-    div.song-info-sep {
-        display: none;
-    }
-}
-
 .song-title a {
     text-decoration: none;
 }
@@ -581,7 +630,7 @@ div.comment-button-container {
 
 div.player-container {
     position: fixed;
-    max-width: 700px;
+    max-width: 1200px;
     margin: auto;
     bottom: 0;
     left: 0;
index 5436c236aeabb8ac6bcb6d9e2cfe75975cff9a3a..958f6cad0806f25403bd3217e7cf996eb48577e5 100644 (file)
             <button id="mobile-hide-header-btn" onclick="hideNavMenu()">
                 <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><g fill="none" fill-rule="evenodd"><path d="m12.593 23.258l-.011.002l-.071.035l-.02.004l-.014-.004l-.071-.035q-.016-.005-.024.005l-.004.01l-.017.428l.005.02l.01.013l.104.074l.015.004l.012-.004l.104-.074l.012-.016l.004-.017l-.017-.427q-.004-.016-.017-.018m.265-.113l-.013.002l-.185.093l-.01.01l-.003.011l.018.43l.005.012l.008.007l.201.093q.019.005.029-.008l.004-.014l-.034-.614q-.005-.018-.02-.022m-.715.002a.02.02 0 0 0-.027.006l-.006.014l-.034.614q.001.018.017.024l.015-.002l.201-.093l.01-.008l.004-.011l.017-.43l-.003-.012l-.01-.01z"/><path fill="currentColor" d="m12 14.122l5.303 5.303a1.5 1.5 0 0 0 2.122-2.122L14.12 12l5.304-5.303a1.5 1.5 0 1 0-2.122-2.121L12 9.879L6.697 4.576a1.5 1.5 0 1 0-2.122 2.12L9.88 12l-5.304 5.304a1.5 1.5 0 1 0 2.122 2.12z"/></g></svg>
             </button>
-            <div style="text-align: center;">
-                <!--<img class="title-image littlesongplace02">-->
-                <a href="/" style="text-decoration: none;"><h1>little song place</h1></a>
+
+            <div id="site-title">
+                <a href="/" style="text-decoration: none;">little song place</a>
             </div>
+
             <!-- Navbar/Menu -->
             <div id="navbar">
-                <a href="/jams/1">Jam</a>
-                <a href="/about">About</a>
-                <a href="/site-news">News</a>
-                <a href="/songs">Random</a>
+                <a href="/site-news">site news</a>
+                <a href="/about">about the site</a>
+
+                <!-- <a href="/songs">tunes</a> -->
+                <!-- <a href="/jams/1">jams</a> -->
 
-                <a href="/users/{{ session["username"] }}" class="nav-logged-in" id="my-profile" hidden>My Profile</a>
-                <a href="/activity" class="nav-logged-in" hidden><span id="activity-indicator" hidden></span>Activity</a>
-                <a href="/logout" class="nav-logged-in" hidden>Sign Out</a>
+                <!-- <a href="/users/{{ session["username"] }}" class="nav-logged-in" id="my-profile" hidden>profile</a> -->
+                <!-- <a href="/activity" class="nav-logged-in" hidden><span id="activity-indicator" hidden></span>activity</a> -->
+                <!-- <a href="/logout" class="nav-logged-in" hidden>sign out</a> -->
 
-                <a href="/signup" class="nav-logged-out">Create Account</a>
-                <a href="/login" class="nav-logged-out">Sign In</a>
+                <!-- <a href="/signup" class="nav-logged-out">create account</a> -->
+                <!-- <a href="/login" class="nav-logged-out">sign in</a> -->
 
-                <span class="nav-logged-in" id="logged-in-status" hidden></span>
+                <!-- <span class="nav-logged-in" id="logged-in-status" hidden></span> -->
             </div>
         </div>
 
         <!-- Flashed Status Messages -->
         <div id="flashes-container">
             {% with messages = get_flashed_messages(with_categories=True) -%}
-            {% if messages  -%}
+            {% if messages -%}
             <div class="flashes">
                 <ul>
                     {% for category, message in messages %}
             {%- endwith %}
         </div>
 
-        <!-- Page-Specific Content -->
-        <div class="main" id="main" data-bgcolor="{{ bgcolor }}" data-fgcolor="{{ fgcolor }}" data-accolor="{{ accolor }}" data-username="{{ session['username'] }}">{% block body %}{% endblock %}</div>
+        <div id="outer">
+            <div id="left">
+                <div class="page-section">
+                    <div class="page-section-header">me</div>
+                    <div class="user-list-entry-container">
+                        <a href="/users/{{ g.user.username }}" class="user-list-entry" style="--yellow:{{ g.user.bgcolor }};--black:{{ g.user.fgcolor }};--purple:{{ g.user.accolor }};">
+                            {% if g.user.has_pfp -%}
+                            <img class="small-pfp" src="/pfp/{{ g.user['userid'] }}" width="32" height="32" />
+                            {%- endif %}
+                            <span>{{ g.user.username }}</span>
+                        </a>
+                    </div>
+                    <div id="user-actions">
+                        <a href="/activity" class="nav-logged-in" hidden><span id="activity-indicator" hidden></span>activity</a>
+                        <a href="/logout" class="nav-logged-in" hidden>sign out</a>
+                    </div>
+                </div>
+                {% block left %}{% endblock %}
+            </div>
+
+            <!-- Page-Specific Content -->
+            <div id="main" data-bgcolor="{{ bgcolor }}" data-fgcolor="{{ fgcolor }}" data-accolor="{{ accolor }}" data-username="{{ session['username'] }}">{% block body %}{% endblock %}</div>
+
+            <div id="right">
+                {% block right %}{% endblock %}
+            </div>
+
+        </div> <!-- outer -->
 
         <!-- Padding to prevent player from obscuring content -->
         <div id="scroll-padding"></div>
index bd9cc2a6789fbb7c5f6a871601ef2a9e4810fa3a..35291f43163409dee9fe6724005167c739653251 100644 (file)
@@ -2,37 +2,42 @@
 
 {% block title %}Little Song Place{% endblock %}
 
+{% block left %}
+{% if ongoing_events or upcoming_events %}
+<div class="page-section">
+    <div class="page-section-header">jams</div>
+    {% from "jam-event-list.html" import jam_event_list %}
+    {{ jam_event_list("ongoing events", ongoing_events, "ends", "end") }}
+    {{ jam_event_list("upcoming events", upcoming_events, "starts", "start") }}
+</div>
+{% endif %}
+{% endblock %}
+
 {% block body %}
 
-<h2>hello!</h2>
-<div style="display: flex; flex-direction: row; justify-content: center; gap: 10px; align-items: center;">
-<div>🎶</div>
-<div style="text-align: center;">Welcome to littlesong.place.<br/>Make music, and share it with friends!</div>
-<div>🎵</div>
+<div class="page-section">
+    <div class="page-section-header">tunes</div>
+    {% include "song-list.html" %}
 </div>
 
-{% if ongoing_events or upcoming_events %}
-<h2>happenings</h2>
-{% from "jam-event-list.html" import jam_event_list %}
-{{ jam_event_list("ongoing events", ongoing_events, "ends", "end") }}
-{{ jam_event_list("upcoming events", upcoming_events, "starts", "start") }}
-{% endif %}
+{% endblock %}
 
-<h2>humans</h2>
-<div class="user-list">
-    {% for user in users %}
-    <div class="user-list-entry-container">
-        <a href="/users/{{ user['username'] }}" class="user-list-entry" style="--yellow:{{ user['bgcolor'] }};--black:{{ user['fgcolor'] }};--purple:{{ user['accolor'] }};">
-            {% if user['has_pfp'] -%}
-            <img class="small-pfp" src="/pfp/{{ user['userid'] }}" width="32" height="32" />
-            {%- endif %}
-            <span>{{ user['username'] }}</span>
-        </a>
+{% block right %}
+
+<div class="page-section">
+    <div class="page-section-header">folks</div>
+    <div class="user-list">
+        {% for user in users %}
+        <div class="user-list-entry-container">
+            <a href="/users/{{ user['username'] }}" class="user-list-entry" style="--yellow:{{ user['bgcolor'] }};--black:{{ user['fgcolor'] }};--purple:{{ user['accolor'] }};">
+                {% if user['has_pfp'] -%}
+                <img class="small-pfp" src="/pfp/{{ user['userid'] }}" width="32" height="32" />
+                {%- endif %}
+                <span>{{ user['username'] }}</span>
+            </a>
+        </div>
+        {% endfor %}
     </div>
-    {% endfor %}
 </div>
 
-<h2>hot new tunes</h2>
-{% include "song-list.html" %}
-
 {% endblock %}
index f272529c97e8753156b91297712b4b5d0eb07d77..d8b604c089674e2ee578ad0aa05774abddf58832 100644 (file)
         <a href="/song/{{ song.userid }}/{{ song.songid }}?action=view">{{ song.title }}</a>
     </div>
 
-    <!-- Separator -->
-    <div class="song-info-sep"> - </div>
-
-
     <!-- Song Artist(s) -->
     {{ song_artist(song) | indent(4) }}
 </div>
index 857196d48e29af698aae92b814a5007492d0b57b..974365f2119cef6ffa4b7909b3bdcf2a7224b616 100644 (file)
@@ -10,6 +10,10 @@ class User:
     bgcolor: str
     accolor: str
 
+    @property
+    def has_pfp(self):
+        return user_has_pfp(self.userid)
+
     @property
     def colors(self):
         return {