From c71f4eb68c808a797635ea3a40224e0735749c31 Mon Sep 17 00:00:00 2001 From: Disco DeDisco Date: Tue, 24 Mar 2026 17:19:09 -0400 Subject: [PATCH] styled more of Most Recent applet, allowing for scrolling of 36 most recent events and Load More link --- .../tests/integrated/test_billboard_views.py | 24 ++++++++++ src/apps/billboard/views.py | 2 +- src/apps/drama/models.py | 2 +- src/static_src/scss/_billboard.scss | 45 +++++++++++++++++++ .../_applet-billboard-most-recent.html | 26 +++++++++-- 5 files changed, 94 insertions(+), 5 deletions(-) diff --git a/src/apps/billboard/tests/integrated/test_billboard_views.py b/src/apps/billboard/tests/integrated/test_billboard_views.py index 5114109..4c6b3e7 100644 --- a/src/apps/billboard/tests/integrated/test_billboard_views.py +++ b/src/apps/billboard/tests/integrated/test_billboard_views.py @@ -53,6 +53,30 @@ class BillboardViewTest(TestCase): self.assertEqual(response.context["recent_room"], room) self.assertEqual(len(response.context["recent_events"]), 1) + def test_recent_events_capped_at_36(self): + room = Room.objects.create(name="Test Room", owner=self.user) + for i in range(40): + record( + room, GameEvent.SLOT_FILLED, actor=self.user, + slot_number=1, token_type="coin", + token_display="Coin-on-a-String", renewal_days=7, + ) + response = self.client.get("/billboard/") + self.assertEqual(len(response.context["recent_events"]), 36) + + def test_recent_events_in_chronological_order(self): + room = Room.objects.create(name="Test Room", owner=self.user) + for _ in range(3): + record( + room, GameEvent.SLOT_FILLED, actor=self.user, + slot_number=1, token_type="coin", + token_display="Coin-on-a-String", renewal_days=7, + ) + response = self.client.get("/billboard/") + events = response.context["recent_events"] + timestamps = [e.timestamp for e in events] + self.assertEqual(timestamps, sorted(timestamps)) + def test_recent_room_is_none_when_no_events(self): response = self.client.get("/billboard/") self.assertIsNone(response.context["recent_room"]) diff --git a/src/apps/billboard/views.py b/src/apps/billboard/views.py index b2a0826..3dd3844 100644 --- a/src/apps/billboard/views.py +++ b/src/apps/billboard/views.py @@ -27,7 +27,7 @@ def billboard(request): .first() ) recent_events = ( - recent_room.events.select_related("actor").order_by("-timestamp")[:10] + list(recent_room.events.select_related("actor").order_by("-timestamp")[:36])[::-1] if recent_room else [] ) diff --git a/src/apps/drama/models.py b/src/apps/drama/models.py index 7572cc7..0866488 100644 --- a/src/apps/drama/models.py +++ b/src/apps/drama/models.py @@ -73,7 +73,7 @@ class GameEvent(models.Model): } code = d.get("role", "?") role = d.get("role_display") or _role_names.get(code, code) - return f"starts as {role}" + return f"elects to start as {role}" if self.verb == self.ROLES_REVEALED: return "All roles assigned" return self.verb diff --git a/src/static_src/scss/_billboard.scss b/src/static_src/scss/_billboard.scss index 00b4464..042d7e9 100644 --- a/src/static_src/scss/_billboard.scss +++ b/src/static_src/scss/_billboard.scss @@ -71,6 +71,51 @@ body.page-billscroll { } } +// ── Billboard applet placement ───────────────────────────────────────────── +// Explicit placement: My Scrolls + Contacts stack left, Most Recent fills right. +// Portrait override (container query) restores stacked full-width layout. + +#id_billboard_applets_container { + #id_applet_billboard_my_scrolls { grid-column: 1 / span 4; grid-row: 1 / span 3; } + #id_applet_billboard_my_contacts { grid-column: 1 / span 4; grid-row: 4 / span 3; } + #id_applet_billboard_most_recent { grid-column: 5 / span 8; grid-row: 1 / span 6; } + + @container (max-width: 550px) { + #id_applet_billboard_my_scrolls, + #id_applet_billboard_my_contacts, + #id_applet_billboard_most_recent { + grid-column: 1 / span 12; + grid-row: span var(--applet-rows, 3); + } + } +} + +// ── Most Recent applet — scrollable drama feed ───────────────────────────── + +#id_applet_billboard_most_recent { + display: flex; + flex-direction: column; + + .most-recent-room-link { + flex-shrink: 0; + margin-bottom: 0.25rem; + font-weight: bold; + } + + #id_drama_scroll { + flex: 1; + min-height: 0; + overflow-y: auto; + } + + .most-recent-load-more { + display: block; + padding-bottom: 0.5rem; + font-size: 0.8rem; + text-align: center; + } +} + // ── My Scrolls list ──────────────────────────────────────────────────────── #id_applet_billboard_my_scrolls { diff --git a/src/templates/apps/billboard/_partials/_applet-billboard-most-recent.html b/src/templates/apps/billboard/_partials/_applet-billboard-most-recent.html index 9a04953..f28169d 100644 --- a/src/templates/apps/billboard/_partials/_applet-billboard-most-recent.html +++ b/src/templates/apps/billboard/_partials/_applet-billboard-most-recent.html @@ -1,3 +1,4 @@ +{% load lyric_extras %}
Most Recent {% if recent_room %} {{ recent_room.name }} - {% with events=recent_events %} - {% include "core/_partials/_scroll.html" %} - {% endwith %} +
+ Load more…. + {% for event in recent_events %} +
+ + {{ event.actor|display_name }} + {{ event.to_prose }}
+ +
+
+ {% empty %} +

No events yet.

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

No recent activity.

{% endif %}
+