Add Day Started event to activity log with template name

- On session start, insert a session_start TimerEvent so the action
  appears in the activity log timeline
- Load DailySession.template via selectinload in the timeline query
  so the template name is available without extra round-trips
- _to_timeline_out maps the template name into block_label for
  session_start events, displaying as "Day started — Template Name"
- Add session_start to EVENT_META on the frontend (🏫 icon)
- Hide the Edit button for session_start entries since changing their
  event type to a block-level action doesn't make sense

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-03-01 14:22:07 -08:00
parent 823260cdd8
commit 37416436ba
3 changed files with 25 additions and 9 deletions

View File

@@ -31,7 +31,10 @@ async def get_timeline(
.where(Child.user_id == current_user.id) .where(Child.user_id == current_user.id)
.options( .options(
selectinload(TimerEvent.block).selectinload(ScheduleBlock.subject), selectinload(TimerEvent.block).selectinload(ScheduleBlock.subject),
selectinload(TimerEvent.session).selectinload(DailySession.child), selectinload(TimerEvent.session).options(
selectinload(DailySession.child),
selectinload(DailySession.template),
),
) )
.order_by(TimerEvent.occurred_at.desc()) .order_by(TimerEvent.occurred_at.desc())
) )
@@ -49,6 +52,10 @@ async def get_timeline(
def _to_timeline_out(e: TimerEvent) -> TimelineEventOut: def _to_timeline_out(e: TimerEvent) -> TimelineEventOut:
blk = e.block blk = e.block
sub = blk.subject if blk else None sub = blk.subject if blk else None
if e.event_type == "session_start":
block_label = e.session.template.name if e.session.template else None
else:
block_label = (blk.label or sub.name) if blk and sub else (blk.label if blk else None)
return TimelineEventOut( return TimelineEventOut(
id=e.id, id=e.id,
event_type=e.event_type, event_type=e.event_type,
@@ -56,7 +63,7 @@ def _to_timeline_out(e: TimerEvent) -> TimelineEventOut:
session_date=e.session.session_date, session_date=e.session.session_date,
child_id=e.session.child_id, child_id=e.session.child_id,
child_name=e.session.child.name, child_name=e.session.child.name,
block_label=(blk.label or sub.name) if blk and sub else (blk.label if blk else None), block_label=block_label,
subject_name=sub.name if sub else None, subject_name=sub.name if sub else None,
subject_icon=sub.icon if sub else None, subject_icon=sub.icon if sub else None,
subject_color=sub.color if sub else None, subject_color=sub.color if sub else None,
@@ -71,7 +78,10 @@ async def _get_timer_event(event_id: int, current_user: User, db: AsyncSession)
.where(TimerEvent.id == event_id, Child.user_id == current_user.id) .where(TimerEvent.id == event_id, Child.user_id == current_user.id)
.options( .options(
selectinload(TimerEvent.block).selectinload(ScheduleBlock.subject), selectinload(TimerEvent.block).selectinload(ScheduleBlock.subject),
selectinload(TimerEvent.session).selectinload(DailySession.child), selectinload(TimerEvent.session).options(
selectinload(DailySession.child),
selectinload(DailySession.template),
),
) )
) )
event = result.scalar_one_or_none() event = result.scalar_one_or_none()

View File

@@ -126,6 +126,11 @@ async def start_session(
db.add(session) db.add(session)
await db.commit() await db.commit()
await db.refresh(session) await db.refresh(session)
# Record session start as a timer event so it appears in the activity log
db.add(TimerEvent(session_id=session.id, block_id=None, event_type="session_start"))
await db.commit()
await _broadcast_session(db, session) await _broadcast_session(db, session)
return session return session

View File

@@ -101,7 +101,7 @@
</div> </div>
</div> </div>
<div class="row-actions"> <div class="row-actions">
<button class="btn-sm" @click="startEdit(entry)">Edit</button> <button class="btn-sm" v-if="entry.event_type !== 'session_start'" @click="startEdit(entry)">Edit</button>
<button class="btn-sm btn-danger" @click="deleteEntry(entry)"></button> <button class="btn-sm btn-danger" @click="deleteEntry(entry)"></button>
</div> </div>
</div> </div>
@@ -183,6 +183,7 @@ function fmtTime(isoStr) {
} }
const EVENT_META = { const EVENT_META = {
session_start: { icon: '🏫', label: 'Day started' },
start: { icon: '▶', label: 'Started' }, start: { icon: '▶', label: 'Started' },
pause: { icon: '⏸', label: 'Paused' }, pause: { icon: '⏸', label: 'Paused' },
resume: { icon: '↺', label: 'Resumed' }, resume: { icon: '↺', label: 'Resumed' },