Files
python-tdd/src/templates/apps/billboard/_partials/_applet-most-recent-scroll.html

35 lines
1.5 KiB
HTML
Raw Normal View History

{% load lyric_extras %}
<section
id="id_applet_most_recent_scroll"
style="--applet-cols: {{ entry.applet.grid_cols }}; --applet-rows: {{ entry.applet.grid_rows }};"
>
<h2>Most Recent Scroll</h2>
{% if recent_room %}
<a href="{% url 'billboard:scroll' recent_room.id %}" class="most-recent-room-link">{{ recent_room.name }}</a>
<section id="id_drama_scroll" class="drama-scroll">
<a href="{% url 'billboard:scroll' recent_room.id %}" class="most-recent-load-more">Load more….</a>
{% for event in recent_events %}
<div class="drama-event {% if event.actor == viewer %}mine{% else %}theirs{% endif %}">
<span class="drama-event-body{% if event.struck %} struck{% endif %}">
<strong>{{ event.actor|display_name }}</strong>
{{ event.to_prose|safe }}
</span>
<time class="drama-event-time" datetime="{{ event.timestamp|date:'c' }}">
{{ event.timestamp|relative_ts }}
</time>
</div>
{% empty %}
<p class="event-empty"><small>No events yet.</small></p>
{% endfor %}
</section>
{% else %}
applet feed unification — My Buds + My Notes drop the [Feature forthcoming] / empty placeholders for live top-3 feeds, mirroring the long-standing My Posts pattern; all five in-grid list applets (My Posts / My Buds / My Notes / My Scrolls / My Games) now route their <ul> through a single shared partial `_applet-grid-list.html` (newly extracted) so item rendering + empty-state row + scroll-buffer all live in one place — `_applet-list-shell.html` (the dedicated billbuds/billposts page shell) now internally includes the same grid-list partial for its inner <ul>, so the dedicated-page and in-grid lists share the same skeleton; new per-applet item partials `_my_buds_applet_item.html` (mirrors `_my_buds_item.html` w. data-bud-id + display_name), `_my_notes_item.html` (links to billboard:my_notes; uses display_name), `_my_posts_applet_item.html` (Post link + title), `_my_scrolls_item.html` (Room link to billboard:scroll), `_my_games_item.html` (Room link to epic:gatekeeper); view-side `_billboard_context` gains `_recent_buds(user)` — sorts the User.buds auto-through table by `-id` so newest-added-first w.o. an explicit through model w. timestamps (manage `[r.to_user for r in rows]`) — + `_recent_notes(user)` (`user.notes.order_by('-earned_at')[:limit]`); same two helpers threaded into `new_post`'s GET-with-form-errors branch (line 270-274) so the rerender keeps the new applet content visible; 7 ITs added to BillboardViewTest covering recent_buds ordering / cap / empty + recent_notes ordering / cap / cross-user isolation / empty; SCSS — `.applet-list / .applet-list-entry / .applet-list-buffer` lifted from `.applet-list-page .applet-scroll` scope to top level so they apply in both surfaces; in-grid applets get `display: flex; flex-direction: column; .applet-list { flex: 1 }` so the list scrolls within the applet box; `#id_applet_my_games` ul-centring + `.scroll-list` + `#id_applet_notes h2 { writing-mode: vertical-rl ... }` overrides removed (centring was an empty-state-only behaviour, scroll-list + vertical-rl redundant w. the new shared rule + the %applet-box `> h2` rule); My Games items now left-aligned by default; empty-state row recovers the centred-italic-dim treatment via `.applet-list-entry--empty { flex: 1; display: flex; align-items: center; justify-content: center; opacity: 0.6; font-style: italic }` + `.applet-list:has(> .applet-list-entry--empty) { display: flex; flex-direction: column }` — so "No buds yet" / "No notes yet" / "No games yet" / "No scrolls yet" / "No posts yet" all centre in their applet aperture, reverting to the left-aligned stack the moment a real item lands; Most Recent Scroll's outer empty `<p><small>No recent activity.</small></p>` adopts the same `.applet-list-entry .applet-list-entry--empty` classes (section is already flex-column from existing rule) so it picks up the unified centred-italic-dim treatment pipeline fix — `_post_gear.html` (commit 6a7464e) gated the NVM target on `{% url 'billboard:my_posts' user_id=request.user.id %}`, which exploded w. NoReverseMatch when an anonymous user (Percival ch.18 anonymous-post lab — ownerless `Post.objects.create()`) hit view_post (which has no @login_required); whole gear-include now wrapped in `{% if request.user.is_authenticated %}` since anonymous viewers can't DEL/BYE/back-to-my-posts anyway; AnonymousPostViewerTest pins the 200-render + gear-absence contract so future ownerless-post regressions surface in ITs (pipeline run #298 fixed) — TDD Code architected by Disco DeDisco <discodedisco@outlook.com> Git commit message Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-12 22:48:32 -04:00
<p class="applet-list-entry applet-list-entry--empty">No recent activity.</p>
{% endif %}
</section>
<script>
(function() {
var scroll = document.getElementById('id_drama_scroll');
if (scroll) scroll.scrollTop = scroll.scrollHeight;
})();
</script>