tags: list[str]
collaborators: list[str]
user_has_pfp: bool
+ hidden: bool
def json(self):
return json.dumps(vars(self))
""",
[eventid])
+def _get_song_info_list(table, column, songid):
+ rows = db.query(
+ f"SELECT ({column}) FROM {table} WHERE songid = ?", [songid])
+ return [r[column] for r in rows if r[column]]
+
def _from_db(query, args=()):
songs_data = db.query(query, args)
- tags, collabs = _get_info_for_songs(songs_data)
songs = []
for sd in songs_data:
- song_tags = [t["tag"] for t in tags[sd["songid"]] if t["tag"]]
- song_collabs = [c["name"] for c in collabs[sd["songid"]] if c["name"]]
- created = datetime.fromisoformat(sd["created"]).astimezone().strftime("%Y-%m-%d")
- has_pfp = users.user_has_pfp(sd["userid"])
+ songid = sd["songid"]
+ song_tags = _get_song_info_list("song_tags", "tag", songid)
+ song_collabs = _get_song_info_list("song_collaborators", "name", songid)
+
+ # Song is hidden if it was submitted to an event that hasn't ended yet
+ hidden = False
+ if sd["eventid"]:
+ event_row = db.query(
+ "SELECT * FROM jam_events WHERE eventid = ?",
+ [sd["eventid"]],
+ one=True)
+ if event_row and event_row["enddate"]:
+ enddate = datetime.fromisoformat(event_row["enddate"]).astimezone()
+ hidden = datetime.now().astimezone() < enddate
+
+ created = (
+ datetime.fromisoformat(sd["created"])
+ .astimezone()
+ .strftime("%Y-%m-%d"))
+
songs.append(Song(
- sd["songid"],
- sd["userid"],
- sd["threadid"],
- sd["username"],
- sd["title"],
- sanitize_user_text(sd["description"]),
- created,
- song_tags,
- song_collabs,
- has_pfp
+ songid=sd["songid"],
+ userid=sd["userid"],
+ threadid=sd["threadid"],
+ username=sd["username"],
+ title=sd["title"],
+ description=sanitize_user_text(sd["description"]),
+ created=created,
+ tags=song_tags,
+ collaborators=song_collabs,
+ user_has_pfp=users.user_has_pfp(sd["userid"]),
+ hidden=hidden,
))
return songs
-def _get_info_for_songs(songs):
- tags = {}
- collabs = {}
- for song in songs:
- songid = song["songid"]
- tags[songid] = db.query(
- """
- select (tag) from song_tags
- where songid = ?
- """,
- [songid])
- collabs[songid] = db.query(
- """
- select (name) from song_collaborators
- where songid = ?
- """,
- [songid])
- return tags, collabs
-
@bp.get("/edit-song")
def edit_song():
if not "userid" in session:
margin: 10px 0px;
}
-.playlist-type {
+.visibility-indicator {
opacity: 50%;
}
<p>
Playlist by <a href="/users/{{ username }}" class="profile-link">{{ username }}</a>
{% if session["userid"] == userid -%}
-<span class="playlist-type">
+<span class="visibility-indicator">
[{% if private %}Private{% else %}Public{% endif %}]
</span>
{%- endif %}
<a class="playlist-name" href="/playlists/{{ plist['playlistid'] }}">{{ plist['name'] }}</a>
<!-- Only show playlist type to owner, everyone else only sees public playlists -->
{% if session["userid"] == userid -%}
- <span class="playlist-type">
+ <span class="visibility-indicator">
[{% if plist['private'] %}Private{% else %}Public{% endif %}]
</span>
{%- endif %}
<div class="song-list-songs">
{% for song in songs %}
+ {%- if not (song.hidden and g.uiserid != song.userid) -%}
<div class="song" data-song="{{ song.json() }}">
<div class="song-main">
<div class="song-list-pfp-container">
</div>
{{ song_details(song, current_user_playlists) | indent(8) }}
</div>
+ {%- endif -%}
{% endfor %}
</div>
</div>
{% macro song_info(song) %}
<div class="song-info">
<!-- Song Title -->
- <div class="song-title"><a href="/song/{{ song.userid }}/{{ song.songid }}?action=view">{{ song.title }}</a></div>
+ <div class="song-title"><a href="/song/{{ song.userid }}/{{ song.songid }}?action=view">{{ song.title }}</a>
+ {%- if song.hidden %}<span class="visibility-indicator">[Hidden]</span>{% endif -%}
+ </div>
<!-- Separator -->
- <div class="song-info-sep">
- -
- </div>
+ <div class="song-info-sep"> - </div>
+
<!-- Song Artist(s) -->
{{ song_artist(song) | indent(4) }}
from .utils import create_user, upload_song
+# Shared timestamps
+today = datetime.now(timezone.utc)
+yesterday = (today - timedelta(days=1)).isoformat()
+tomorrow = (today + timedelta(days=1)).isoformat()
+
@pytest.fixture
def user(client):
create_user(client, "user", login=True)
last_index = index
def _create_past_present_future_events(client, jam):
- today = datetime.now(timezone.utc)
- yesterday = (today - timedelta(days=1)).isoformat()
- tomorrow = (today + timedelta(days=1)).isoformat()
-
_create_event(client, jam, "PastJam", yesterday, yesterday)
_create_event(client, jam, "OngoingJam", yesterday, tomorrow)
_create_event(client, jam, "UpcomingJam", tomorrow, tomorrow)
# Song Submissions #############################################################
def test_submit_song_to_event(client, user, jam, event):
+ # Song always visible to owner
+ upload_song(client, b"Success", eventid=event)
+ response = client.get(f"/jams/{jam}/events/{event}")
+ assert b"song title" in response.data
+
+def test_submitted_song_hidden_before_enddate(client, user, jam, event):
+ response = client.post(
+ f"/jams/{jam}/events/{event}/update",
+ data=_get_event_data(enddate=tomorrow),
+ follow_redirects=True)
upload_song(client, b"Success", eventid=event)
+ client.get("/logout") # Log out to test public visibility
+
+ response = client.get(f"/jams/{jam}/events/{event}")
+ assert b"song title" not in response.data
+
+def test_submitted_song_visible_after_enddate(client, user, jam, event):
+ response = client.post(
+ f"/jams/{jam}/events/{event}/update",
+ data=_get_event_data(enddate=yesterday),
+ follow_redirects=True)
+ upload_song(client, b"Success", eventid=event)
+ client.get("/logout") # Log out to test public visibility
+
response = client.get(f"/jams/{jam}/events/{event}")
assert b"song title" in response.data