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:
@@ -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()
|
||||||
|
|||||||
@@ -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
|
||||||
|
|
||||||
|
|||||||
@@ -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,11 +183,12 @@ function fmtTime(isoStr) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const EVENT_META = {
|
const EVENT_META = {
|
||||||
start: { icon: '▶', label: 'Started' },
|
session_start: { icon: '🏫', label: 'Day started' },
|
||||||
pause: { icon: '⏸', label: 'Paused' },
|
start: { icon: '▶', label: 'Started' },
|
||||||
resume: { icon: '↺', label: 'Resumed' },
|
pause: { icon: '⏸', label: 'Paused' },
|
||||||
complete: { icon: '✓', label: 'Completed' },
|
resume: { icon: '↺', label: 'Resumed' },
|
||||||
skip: { icon: '⟶', label: 'Skipped' },
|
complete: { icon: '✓', label: 'Completed' },
|
||||||
|
skip: { icon: '⟶', label: 'Skipped' },
|
||||||
}
|
}
|
||||||
|
|
||||||
function eventIcon(entry) {
|
function eventIcon(entry) {
|
||||||
|
|||||||
Reference in New Issue
Block a user