Add per-block agenda overrides for daily sessions

- Add 📝 Agenda button to each block in Today's Schedule on the Dashboard
- Dialog allows setting a free-text activity/note for that block for the current day
- Agenda replaces subject options in the TV center panel while set; clears on session end
- Backend: new SessionBlockAgenda model, PUT /api/sessions/{id}/blocks/{block_id}/agenda
- Agendas included in dashboard snapshot and session_update WS broadcast
- New agenda_update WS event keeps TV in sync live when agenda is saved or cleared
- Update README with feature description, project structure, and WS event table

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-03-19 07:58:30 -07:00
parent d724262e27
commit fdd85d3df5
9 changed files with 246 additions and 17 deletions

View File

@@ -10,6 +10,7 @@ from app.models.morning_routine import MorningRoutineItem
from app.models.break_activity import BreakActivityItem
from app.models.strike import StrikeEvent
from app.models.rule import RuleItem
from app.models.session_block_agenda import SessionBlockAgenda
__all__ = [
"Base",
@@ -28,4 +29,5 @@ __all__ = [
"BreakActivityItem",
"StrikeEvent",
"RuleItem",
"SessionBlockAgenda",
]

View File

@@ -0,0 +1,18 @@
from sqlalchemy import ForeignKey, Text, UniqueConstraint
from sqlalchemy.orm import Mapped, mapped_column
from app.models.base import Base
class SessionBlockAgenda(Base):
__tablename__ = "session_block_agendas"
__table_args__ = (UniqueConstraint("session_id", "block_id"),)
id: Mapped[int] = mapped_column(primary_key=True, autoincrement=True)
session_id: Mapped[int] = mapped_column(
ForeignKey("daily_sessions.id", ondelete="CASCADE"), nullable=False
)
block_id: Mapped[int] = mapped_column(
ForeignKey("schedule_blocks.id", ondelete="CASCADE"), nullable=False
)
text: Mapped[str] = mapped_column(Text, nullable=False)