brief sprint C2: introduce billboard.Brief notification model + view_post marks-read on GET — TDD
Brief is the slide-down-banner record that connects an event (a Line freshly appended to a Post) to a user who needs to see it. It's the C3 attachment point for note-unlock + share-invite + future event sources; the banner JS (C3) reads the Brief shape to render kind-specific affordances. C2 lays the schema + the FYI-read contract; C3 hooks the senders. Schema (billboard.Brief): - owner FK→lyric.User (related_name='briefs') — required; whose attention this is for - post FK→billboard.Post (related_name='briefs') — required; where FYI navigates - line FK→billboard.Line (related_name='briefs', null=True) — the appended Line that triggered the Brief; nullable for share-invite-style flows where the Line write races behind the Brief - is_unread BooleanField default=True — flips on view_post GET - kind CharField (note_unlock | user_post | share_invite, default=user_post) — drives banner-side affordances - title CharField (blank=True) — banner display title - created_at DateTimeField (default=timezone.now) — Meta.ordering='-created_at' view_post (the post-detail GET) now bulk-updates is_unread=False on every Brief where owner == request.user AND post == our_post AND is_unread=True. POST (the compose-a-new-Line path) intentionally does NOT mark read — the user is authoring, not reviewing. Tests: BriefModelTest (7) covers defaults, kind choices include all three values, line nullability, owner+post requiredness, title field, __str__ shape. ViewPostMarksReadTest (5) covers the GET flips owner's unread Brief to read; doesn't flip other users' Briefs on the same post; doesn't flip Briefs on unrelated posts; idempotent for already-read; POST request does NOT mark read. Auto migration billboard/0002_brief creates the table. 801-test IT regression green (789 + 12 new). Code architected by Disco DeDisco <discodedisco@outlook.com> Git commit message Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -9,7 +9,7 @@ from django.shortcuts import redirect, render
|
||||
|
||||
from apps.applets.utils import applet_context, apply_applet_toggle
|
||||
from apps.billboard.forms import ExistingPostLineForm, LineForm
|
||||
from apps.billboard.models import Post
|
||||
from apps.billboard.models import Brief, Post
|
||||
from apps.dashboard.views import _PALETTE_DEFS
|
||||
from apps.drama.models import GameEvent, Note, ScrollPosition
|
||||
from apps.epic.models import Room
|
||||
@@ -253,6 +253,14 @@ def view_post(request, post_id):
|
||||
if form.is_valid():
|
||||
form.save()
|
||||
return redirect(our_post)
|
||||
|
||||
# GET render is the FYI-read contract — flip every unread Brief on this
|
||||
# post for the requesting user. POST (compose) is intentionally excluded
|
||||
# because the user is authoring, not reviewing the new Line.
|
||||
if request.user.is_authenticated:
|
||||
Brief.objects.filter(
|
||||
owner=request.user, post=our_post, is_unread=True,
|
||||
).update(is_unread=False)
|
||||
return render(request, "apps/billboard/post.html", {"post": our_post, "form": form})
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user