@recaptime-dev's working patches + fork for Phorge, a community fork of Phabricator. (Upstream dev and stable branches are at upstream/main and upstream/stable respectively.) hq.recaptime.dev/wiki/Phorge
phorge phabricator
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

Move event recurrence controls to a separate page on the workflow

Summary:
Ref T11326. Currently, the "Create Event" form is pretty wordy. One particular culprit is the "recurring" controls, which are (presumably) rarely used and visually complex.

- Reflow the default form to hopefully feel a little better.
- Move recurrence stuff to a separate workflow.

Test Plan:
{F1891355}

{F1891356}

{F1891357}

Reviewers: chad

Reviewed By: chad

Maniphest Tasks: T11326

Differential Revision: https://secure.phabricator.com/D16774

+132 -87
+20 -1
src/applications/calendar/controller/PhabricatorCalendarEventViewController.php
··· 146 146 PhabricatorPolicyCapability::CAN_EDIT); 147 147 148 148 $edit_uri = "event/edit/{$id}/"; 149 + $edit_uri = $this->getApplicationURI($edit_uri); 150 + 149 151 if ($event->isChildEvent()) { 150 152 $edit_label = pht('Edit This Instance'); 151 153 } else { ··· 159 161 id(new PhabricatorActionView()) 160 162 ->setName($edit_label) 161 163 ->setIcon('fa-pencil') 162 - ->setHref($this->getApplicationURI($edit_uri)) 164 + ->setHref($edit_uri) 163 165 ->setDisabled(!$can_edit) 164 166 ->setWorkflow(!$can_edit)); 165 167 } 168 + 169 + $recurring_uri = "{$edit_uri}page/recurring/"; 170 + $can_recurring = $can_edit && !$event->isChildEvent(); 171 + 172 + if ($event->getIsRecurring()) { 173 + $recurring_label = pht('Edit Recurrence'); 174 + } else { 175 + $recurring_label = pht('Make Recurring'); 176 + } 177 + 178 + $curtain->addAction( 179 + id(new PhabricatorActionView()) 180 + ->setName($recurring_label) 181 + ->setIcon('fa-repeat') 182 + ->setHref($recurring_uri) 183 + ->setDisabled(!$can_recurring) 184 + ->setWorkflow(true)); 166 185 167 186 $can_attend = !$event->isImportedEvent(); 168 187
+89 -83
src/applications/calendar/editor/PhabricatorCalendarEventEditEngine.php
··· 67 67 $invitee_phids = $object->getInviteePHIDsForEdit(); 68 68 } 69 69 70 - $frequency_options = array( 71 - PhutilCalendarRecurrenceRule::FREQUENCY_DAILY => pht('Daily'), 72 - PhutilCalendarRecurrenceRule::FREQUENCY_WEEKLY => pht('Weekly'), 73 - PhutilCalendarRecurrenceRule::FREQUENCY_MONTHLY => pht('Monthly'), 74 - PhutilCalendarRecurrenceRule::FREQUENCY_YEARLY => pht('Yearly'), 75 - ); 70 + $frequency_map = PhabricatorCalendarEvent::getFrequencyMap(); 71 + $frequency_options = ipull($frequency_map, 'label'); 72 + 73 + $rrule = $object->newRecurrenceRule(); 74 + if ($rrule) { 75 + $frequency = $rrule->getFrequency(); 76 + } else { 77 + $frequency = null; 78 + } 76 79 77 80 $fields = array( 78 81 id(new PhabricatorTextEditField()) ··· 85 88 ->setConduitDescription(pht('Rename the event.')) 86 89 ->setConduitTypeDescription(pht('New event name.')) 87 90 ->setValue($object->getName()), 88 - id(new PhabricatorRemarkupEditField()) 89 - ->setKey('description') 90 - ->setLabel(pht('Description')) 91 - ->setDescription(pht('Description of the event.')) 91 + id(new PhabricatorBoolEditField()) 92 + ->setKey('isAllDay') 93 + ->setLabel(pht('All Day')) 94 + ->setOptions(pht('Normal Event'), pht('All Day Event')) 95 + ->setTransactionType( 96 + PhabricatorCalendarEventAllDayTransaction::TRANSACTIONTYPE) 97 + ->setDescription(pht('Marks this as an all day event.')) 98 + ->setConduitDescription(pht('Make the event an all day event.')) 99 + ->setConduitTypeDescription(pht('Mark the event as an all day event.')) 100 + ->setValue($object->getIsAllDay()), 101 + id(new PhabricatorEpochEditField()) 102 + ->setKey('start') 103 + ->setLabel(pht('Start')) 104 + ->setIsLockable(false) 105 + ->setIsDefaultable(false) 92 106 ->setTransactionType( 93 - PhabricatorCalendarEventDescriptionTransaction::TRANSACTIONTYPE) 94 - ->setConduitDescription(pht('Update the event description.')) 95 - ->setConduitTypeDescription(pht('New event description.')) 96 - ->setValue($object->getDescription()), 107 + PhabricatorCalendarEventStartDateTransaction::TRANSACTIONTYPE) 108 + ->setDescription(pht('Start time of the event.')) 109 + ->setConduitDescription(pht('Change the start time of the event.')) 110 + ->setConduitTypeDescription(pht('New event start time.')) 111 + ->setValue($object->getStartDateTimeEpoch()), 112 + id(new PhabricatorEpochEditField()) 113 + ->setKey('end') 114 + ->setLabel(pht('End')) 115 + ->setIsLockable(false) 116 + ->setIsDefaultable(false) 117 + ->setTransactionType( 118 + PhabricatorCalendarEventEndDateTransaction::TRANSACTIONTYPE) 119 + ->setDescription(pht('End time of the event.')) 120 + ->setConduitDescription(pht('Change the end time of the event.')) 121 + ->setConduitTypeDescription(pht('New event end time.')) 122 + ->setValue($object->getEndDateTimeEpoch()), 97 123 id(new PhabricatorBoolEditField()) 98 124 ->setKey('cancelled') 99 125 ->setOptions(pht('Active'), pht('Cancelled')) ··· 128 154 ->setConduitTypeDescription(pht('New event invitees.')) 129 155 ->setValue($invitee_phids) 130 156 ->setCommentActionLabel(pht('Change Invitees')), 131 - ); 132 - 133 - if ($this->getIsCreate()) { 134 - $fields[] = id(new PhabricatorBoolEditField()) 157 + id(new PhabricatorRemarkupEditField()) 158 + ->setKey('description') 159 + ->setLabel(pht('Description')) 160 + ->setDescription(pht('Description of the event.')) 161 + ->setTransactionType( 162 + PhabricatorCalendarEventDescriptionTransaction::TRANSACTIONTYPE) 163 + ->setConduitDescription(pht('Update the event description.')) 164 + ->setConduitTypeDescription(pht('New event description.')) 165 + ->setValue($object->getDescription()), 166 + id(new PhabricatorIconSetEditField()) 167 + ->setKey('icon') 168 + ->setLabel(pht('Icon')) 169 + ->setIconSet(new PhabricatorCalendarIconSet()) 170 + ->setTransactionType( 171 + PhabricatorCalendarEventIconTransaction::TRANSACTIONTYPE) 172 + ->setDescription(pht('Event icon.')) 173 + ->setConduitDescription(pht('Change the event icon.')) 174 + ->setConduitTypeDescription(pht('New event icon.')) 175 + ->setValue($object->getIcon()), 176 + id(new PhabricatorBoolEditField()) 177 + ->setIsHidden($object->getIsRecurring()) 135 178 ->setKey('isRecurring') 136 179 ->setLabel(pht('Recurring')) 137 180 ->setOptions(pht('One-Time Event'), pht('Recurring Event')) ··· 140 183 ->setDescription(pht('One time or recurring event.')) 141 184 ->setConduitDescription(pht('Make the event recurring.')) 142 185 ->setConduitTypeDescription(pht('Mark the event as a recurring event.')) 143 - ->setValue($object->getIsRecurring()); 144 - 145 - 146 - $rrule = $object->newRecurrenceRule(); 147 - if ($rrule) { 148 - $frequency = $rrule->getFrequency(); 149 - } else { 150 - $frequency = null; 151 - } 152 - 153 - $fields[] = id(new PhabricatorSelectEditField()) 186 + ->setValue($object->getIsRecurring()), 187 + id(new PhabricatorSelectEditField()) 154 188 ->setKey('frequency') 155 189 ->setLabel(pht('Frequency')) 156 190 ->setOptions($frequency_options) ··· 159 193 ->setDescription(pht('Recurring event frequency.')) 160 194 ->setConduitDescription(pht('Change the event frequency.')) 161 195 ->setConduitTypeDescription(pht('New event frequency.')) 162 - ->setValue($frequency); 163 - } 164 - 165 - if ($this->getIsCreate() || $object->getIsRecurring()) { 166 - $fields[] = id(new PhabricatorEpochEditField()) 196 + ->setValue($frequency), 197 + id(new PhabricatorEpochEditField()) 167 198 ->setIsLockable(false) 168 199 ->setIsDefaultable(false) 169 200 ->setAllowNull(true) 201 + ->setHideTime($object->getIsAllDay()) 170 202 ->setKey('until') 171 203 ->setLabel(pht('Repeat Until')) 172 204 ->setTransactionType( ··· 174 206 ->setDescription(pht('Last instance of the event.')) 175 207 ->setConduitDescription(pht('Change when the event repeats until.')) 176 208 ->setConduitTypeDescription(pht('New final event time.')) 177 - ->setValue($object->getUntilDateTimeEpoch()); 178 - } 179 - 180 - $fields[] = id(new PhabricatorBoolEditField()) 181 - ->setKey('isAllDay') 182 - ->setLabel(pht('All Day')) 183 - ->setOptions(pht('Normal Event'), pht('All Day Event')) 184 - ->setTransactionType( 185 - PhabricatorCalendarEventAllDayTransaction::TRANSACTIONTYPE) 186 - ->setDescription(pht('Marks this as an all day event.')) 187 - ->setConduitDescription(pht('Make the event an all day event.')) 188 - ->setConduitTypeDescription(pht('Mark the event as an all day event.')) 189 - ->setValue($object->getIsAllDay()); 190 - 191 - $fields[] = id(new PhabricatorEpochEditField()) 192 - ->setKey('start') 193 - ->setLabel(pht('Start')) 194 - ->setIsLockable(false) 195 - ->setIsDefaultable(false) 196 - ->setTransactionType( 197 - PhabricatorCalendarEventStartDateTransaction::TRANSACTIONTYPE) 198 - ->setDescription(pht('Start time of the event.')) 199 - ->setConduitDescription(pht('Change the start time of the event.')) 200 - ->setConduitTypeDescription(pht('New event start time.')) 201 - ->setValue($object->getStartDateTimeEpoch()); 202 - 203 - $fields[] = id(new PhabricatorEpochEditField()) 204 - ->setKey('end') 205 - ->setLabel(pht('End')) 206 - ->setIsLockable(false) 207 - ->setIsDefaultable(false) 208 - ->setTransactionType( 209 - PhabricatorCalendarEventEndDateTransaction::TRANSACTIONTYPE) 210 - ->setDescription(pht('End time of the event.')) 211 - ->setConduitDescription(pht('Change the end time of the event.')) 212 - ->setConduitTypeDescription(pht('New event end time.')) 213 - ->setValue($object->getEndDateTimeEpoch()); 214 - 215 - $fields[] = id(new PhabricatorIconSetEditField()) 216 - ->setKey('icon') 217 - ->setLabel(pht('Icon')) 218 - ->setIconSet(new PhabricatorCalendarIconSet()) 219 - ->setTransactionType( 220 - PhabricatorCalendarEventIconTransaction::TRANSACTIONTYPE) 221 - ->setDescription(pht('Event icon.')) 222 - ->setConduitDescription(pht('Change the event icon.')) 223 - ->setConduitTypeDescription(pht('New event icon.')) 224 - ->setValue($object->getIcon()); 209 + ->setValue($object->getUntilDateTimeEpoch()), 210 + ); 225 211 226 212 return $fields; 227 213 } ··· 263 249 } 264 250 } 265 251 252 + return $fields; 253 + } 266 254 255 + protected function newPages($object) { 256 + // Controls for event recurrence behavior go on a separate page which we 257 + // put in a dialog. This simplifies event creation in the common case. 267 258 268 - return $fields; 259 + return array( 260 + id(new PhabricatorEditPage()) 261 + ->setKey('core') 262 + ->setLabel(pht('Core')) 263 + ->setIsDefault(true), 264 + id(new PhabricatorEditPage()) 265 + ->setKey('recurring') 266 + ->setLabel(pht('Recurrence')) 267 + ->setFieldKeys( 268 + array( 269 + 'isRecurring', 270 + 'frequency', 271 + 'until', 272 + )), 273 + ); 269 274 } 275 + 270 276 }
+17
src/applications/calendar/storage/PhabricatorCalendarEvent.php
··· 461 461 return $this->assertAttached($this->invitees); 462 462 } 463 463 464 + public static function getFrequencyMap() { 465 + return array( 466 + PhutilCalendarRecurrenceRule::FREQUENCY_DAILY => array( 467 + 'label' => pht('Daily'), 468 + ), 469 + PhutilCalendarRecurrenceRule::FREQUENCY_WEEKLY => array( 470 + 'label' => pht('Weekly'), 471 + ), 472 + PhutilCalendarRecurrenceRule::FREQUENCY_MONTHLY => array( 473 + 'label' => pht('Monthly'), 474 + ), 475 + PhutilCalendarRecurrenceRule::FREQUENCY_YEARLY => array( 476 + 'label' => pht('Yearly'), 477 + ), 478 + ); 479 + } 480 + 464 481 private function newStubInvitees() { 465 482 $parent = $this->getParentEvent(); 466 483
+6 -3
src/applications/calendar/xaction/PhabricatorCalendarEventRecurringTransaction.php
··· 30 30 continue; 31 31 } 32 32 33 + if ($xaction->getNewValue()) { 34 + continue; 35 + } 36 + 33 37 $errors[] = $this->newInvalidError( 34 38 pht( 35 - 'An event can only be made recurring when it is created. '. 36 - 'You can not convert an existing event into a recurring '. 37 - 'event or vice versa.'), 39 + 'An event can not be stopped from recurring once it has been '. 40 + 'made recurring. You can cancel the event.'), 38 41 $xaction); 39 42 } 40 43