Show shared-invitee icon on owner's calendar for events with active guests
Adds has_active_invitees flag to the events GET response. The Users icon now appears on the owner's calendar view when an event has accepted or tentative invitees, giving visual feedback that the event is actively shared. Single batch query with set lookup — no N+1. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
c66fd159ea
commit
2f45220c5d
@ -35,6 +35,7 @@ def _event_to_dict(
|
||||
display_calendar_name: str | None = None,
|
||||
display_calendar_color: str | None = None,
|
||||
can_modify: bool = False,
|
||||
has_active_invitees: bool = False,
|
||||
) -> dict:
|
||||
"""Serialize a CalendarEvent ORM object to a response dict including calendar info."""
|
||||
# For invited events: use display calendar if set, otherwise fallback to "Invited"/gray
|
||||
@ -74,6 +75,7 @@ def _event_to_dict(
|
||||
"invitation_id": invitation_id,
|
||||
"display_calendar_id": display_calendar_id,
|
||||
"can_modify": can_modify,
|
||||
"has_active_invitees": has_active_invitees,
|
||||
}
|
||||
return d
|
||||
|
||||
@ -243,6 +245,21 @@ async def get_events(
|
||||
all_event_ids = [e.id for e in events]
|
||||
override_map = await get_invitation_overrides_for_user(db, current_user.id, all_event_ids)
|
||||
|
||||
# Batch-fetch event IDs that have accepted/tentative invitees (for owner's shared icon)
|
||||
active_invitee_set: set[int] = set()
|
||||
if all_event_ids:
|
||||
active_inv_result = await db.execute(
|
||||
select(EventInvitation.event_id).where(
|
||||
EventInvitation.event_id.in_(all_event_ids),
|
||||
EventInvitation.status.in_(["accepted", "tentative"]),
|
||||
).distinct()
|
||||
)
|
||||
active_invitee_set = {r[0] for r in active_inv_result.all()}
|
||||
# Also mark parent events: if a parent has active invitees, all its children should show the icon
|
||||
parent_ids = {e.parent_event_id for e in events if e.parent_event_id and e.parent_event_id in active_invitee_set}
|
||||
if parent_ids:
|
||||
active_invitee_set.update(e.id for e in events if e.parent_event_id in active_invitee_set)
|
||||
|
||||
response: List[dict] = []
|
||||
for e in events:
|
||||
# Determine if this event is from an invitation
|
||||
@ -272,6 +289,7 @@ async def get_events(
|
||||
display_calendar_name=disp_cal_name,
|
||||
display_calendar_color=disp_cal_color,
|
||||
can_modify=inv_can_modify,
|
||||
has_active_invitees=(parent_id in active_invitee_set or e.id in active_invitee_set),
|
||||
))
|
||||
|
||||
# Fetch the user's Birthdays system calendar; only generate virtual events if visible
|
||||
|
||||
@ -389,6 +389,7 @@ export default function CalendarPage() {
|
||||
calendarColor: event.calendar_color || 'hsl(var(--accent-color))',
|
||||
is_invited: event.is_invited,
|
||||
can_modify: event.can_modify,
|
||||
has_active_invitees: event.has_active_invitees,
|
||||
},
|
||||
}));
|
||||
|
||||
@ -531,6 +532,7 @@ export default function CalendarPage() {
|
||||
const isAllDay = arg.event.allDay;
|
||||
const isRecurring = arg.event.extendedProps.is_recurring || arg.event.extendedProps.parent_event_id;
|
||||
const isInvited = arg.event.extendedProps.is_invited;
|
||||
const hasActiveInvitees = arg.event.extendedProps.has_active_invitees;
|
||||
const calColor = arg.event.extendedProps.calendarColor as string;
|
||||
|
||||
// Sync --event-color on the parent FC element so CSS rules (background, hover)
|
||||
@ -544,7 +546,7 @@ export default function CalendarPage() {
|
||||
|
||||
const icons = (
|
||||
<>
|
||||
{isInvited && <Users className="h-2.5 w-2.5 shrink-0 opacity-60" />}
|
||||
{(isInvited || hasActiveInvitees) && <Users className="h-2.5 w-2.5 shrink-0 opacity-60" />}
|
||||
{isRecurring && <Repeat className="h-2.5 w-2.5 shrink-0 opacity-50" />}
|
||||
</>
|
||||
);
|
||||
|
||||
@ -117,6 +117,7 @@ export interface CalendarEvent {
|
||||
invitation_id?: number | null;
|
||||
display_calendar_id?: number | null;
|
||||
can_modify?: boolean;
|
||||
has_active_invitees?: boolean;
|
||||
created_at: string;
|
||||
updated_at: string;
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user