note title equip: DON/DOFF buttons outside top-left corner; User.active_title FK; don/doff views; greeting updated via JS — TDD

- lyric/models.py: active_title = ForeignKey('drama.Note', null=True, SET_NULL)
- lyric migration 0020_add_active_title
- billboard/views.py: don_title + doff_title views; is_equipped per note_item context
- billboard/urls.py: note/<slug>/don + note/<slug>/doff routes
- _navbar.html: id_greeting_name span; shows active_title.slug|capfirst when set
- my_notes.html: .note-don-doff buttons (DON/DOFF, × when disabled); data-don-url/doff-url/title attrs
- note-page.js: _bindDonDoff() — DON POST sets greeting + swaps btn state; DOFF restores Earthman
- _note.scss: .note-don-doff position:absolute left:-1rem top:0; flex-direction:column gap:1.25rem
- ITs: NoteEquipTitleViewTest (5 tests); UserModelTest.test_active_title_* (3 tests)
- FT: NoteEquipTitleTest.test_don_equips_title_greeting_and_doff_restores

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:
Disco DeDisco
2026-04-23 01:44:58 -04:00
parent 7d4389a74a
commit 214120ef2d
12 changed files with 289 additions and 2 deletions

View File

@@ -3,6 +3,7 @@ from django.contrib import auth
from django.test import TestCase
from django.utils import timezone
from apps.drama.models import Note
from apps.lyric.models import LoginToken, PaymentMethod, Token, User, Wallet
@@ -29,6 +30,27 @@ class UserModelTest(TestCase):
user = User.objects.create(email="a@b.cde")
self.assertFalse(user.searchable)
def test_active_title_is_null_by_default(self):
user = User.objects.create(email="a@b.cde")
self.assertIsNone(user.active_title)
def test_active_title_can_be_set_to_a_note(self):
user = User.objects.create(email="a@b.cde")
note = Note.objects.create(user=user, slug="stargazer", earned_at=timezone.now())
user.active_title = note
user.save(update_fields=["active_title"])
user.refresh_from_db()
self.assertEqual(user.active_title, note)
def test_clearing_note_nullifies_active_title(self):
user = User.objects.create(email="a@b.cde")
note = Note.objects.create(user=user, slug="stargazer", earned_at=timezone.now())
user.active_title = note
user.save(update_fields=["active_title"])
note.delete()
user.refresh_from_db()
self.assertIsNone(user.active_title)
class LoginTokenModelTest(TestCase):
def test_links_user_with_autogen_uid(self):
login_token1 = LoginToken.objects.create(email="a@b.cde")