Calendar was originally "Status", and let you list things like vacation/sick days. Consequently, it didn't support invitees.
It has been partially transitioned toward having real events with invitees. This transition should be completed.
Calendar was originally "Status", and let you list things like vacation/sick days. Consequently, it didn't support invitees.
It has been partially transitioned toward having real events with invitees. This transition should be completed.
Status | Assigned | Task | ||
---|---|---|---|---|
Open | epriestley | T7924 Unprototype Calendar (v1) | ||
Duplicate | lpriestley | T7932 Support proper events in Calendar | ||
Resolved | lpriestley | T7988 Create meaningful transaction messages | ||
Resolved | lpriestley | T7986 Inviting people and RSVP'ing to a Calendar event. | ||
Wontfix | lpriestley | T7989 Fill any missing gaps in Calendar event invitee statuses. | ||
Resolved | lpriestley | T7935 Give calendar events real invitee lists | ||
Resolved | lpriestley | T5464 Use ApplicationTransactions in Calendar | ||
Resolved | lpriestley | T7945 Support Edges in Calendar |
I think invitees are complex enough that we probably don't want to use edges to store them. Edges are good for simple relationships (like a user subscribing to an object) but not as good for more complex relationships. Invitees are likely to have a lot of state eventually (required/optional, invited/attending/declined, maybe annotations like "Speaker" for a talk, "Co-Host" for a party, or "Bringing Salad" vs "Bringing Desert" for a potluck, maybe tracking who invited you, and so on).
We can use a custom table to store a complex relationship like this, but we'll have to do more work for it since we get less stuff "for free".
Add Storage: Create a new PhabricatorCalendarEventInvitee class in calendar/storage/ and add a .sql patch to create it. Minimum fields are probably:
If you think any of the other stuff is good and you want to implement it relatively soon, you can add fields for those now. Otherwise, you can wait until later:
Those are just the first three ideas I came up with so we can ignore them for now if they aren't resonating with you as the greatest features in the world, and figure out if they make sense or not later on.
Write a Query Class: Write a PhabricatorCalendarEventInviteeQuery class which extends PhabricatorCursorPagedPolicyAwareQuery. For now, I think this just needs withEventPHIDs($phids) and withInviteePHIDs($phids). You'll have to implement PhabricatorPolicyInterface to support this. You should be able to use an implementation similar to the existing CalendarEvent implementation. You'll be able to test this class in the next step.
Write Stuff to the Database: Next, we want to start writing an invitee row when you create an event. This will invite you to the event.
Define a new transaction type, like PhabricatorCalendarEventTransaction::TYPE_INVITE, and add a transaction for it to the $xactions list in the EditController if a new event is being created.
The "new value" for these transactions will be a little bit complex. A structure like this might work well:
$new = array( $user_phid => PhabricatorCalendarEventInvitee::STATUS_ACCEPTED, );
Meaning "set this user's invitation status to 'accepted', regardless of what their old status was". You'll pass this to setNewValue(...) on the $xaction in the EditController. We're using an array so we can invite a lot of people at once later on.
Inside the Editor, you'll build a similar structure by querying the database:
$old = array( $user_phid => PhabricatorCalendarEventInvitee::STATUS_NOTINVITED, );
So now the transaction means "this user wasn't invited before, but should have an invite with an accepted status after the transaction applies".
In applyApplicationTransactionInternalEffects(), actually apply the transaction:
When you create a new event, this should now write a row into the phabricator_calendar.calendar_eventinvitee row linking you (the event creator) to the event.
Load Invitees: Add a private $invitees = self::ATTACHABLE; property to CalendarEvent. We're going to load invitees unconditionally (every time we load an event) because we'll need them in order to do policy checks later (e.g., you can always see an event if you're invited to it). Add getInvitees() / attachInvitees() methods.
Add (or expand, if it already exitsts) willFilterPage() on CalendarEventQuery:
Show Invitees: On the detail page, use PHUIStatusListView to show invitees and their status. This is the element that Differential uses to show reviewers. We can refine this later.
Get through that first, then we can figure out how the UI should work for inviting people and RSVP'ing to an event.