The calendar admin page.
Interaction model (quorum-designed, 2026-07-09)
What you see is a SET of calendar layers. "Me" is the default set
{me}; viewing one person is a set of size 1; "Everyone" is a
select-all-permitted shortcut, not a mode. Holders of
calendar.view_others get a toolbar "Calendars · N" button opening a
Google-Calendar-style checklist panel: search, Me/Everyone shortcuts,
and a checkbox list where every person carries a deterministic palette
color — events on the grid are tinted with their owner's color instead
of name prefixes. Clicking a NAME solos that person; the checkbox
toggles membership. People without calendar access stay selectable
(their history must remain reviewable) and are badged; people with no
events in the visible range get an "empty" badge.
State
The selection lives in the URL (?people=uuid1,uuid2 or
?people=all; absent = own calendar), so views are shareable and the
back button works. Every mount/patch SANITIZES the list — unknown ids
are dropped, and viewers without calendar.view_others are forced to
{me} regardless of the URL (authorization is enforced on the query
in PhoenixKitCalendar.Events, not just in the template).
Authorization
Page access needs the base calendar key (admin on_mount chain).
Everything finer goes through the Events context, which re-checks the
caller's scope against each event's persisted owner. The modal
authorizes PER EVENT at open time (can_edit_event?), so with
calendar.edit_others you edit anyone's event inline from any view;
without it you get read-only details. Creating needs exactly one
selected calendar you may edit.
Time semantics
Timed events are stored in UTC and shown/entered in the viewer's
timezone (core's offset-hours model: user_timezone column → site
"time_zone" setting → UTC). When the target calendar's owner sits in a
different offset, the modal says so and offers a checkbox to switch
the entry frame to THEIR timezone — toggling re-renders the same
instant, never reinterprets the digits. All-day events use real dates
(no timezone); the form's end date is INCLUSIVE ("last day") and
shifted to the exclusive storage form at this boundary.