@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.

DRAFT, recurring events need optional end dates

Summary: Ref T8357, DRAFT, recurring events need optional end dates

Test Plan: Edit recurring event, set end date, save, recurring ghosts should not generate after end date

Reviewers: #blessed_reviewers, epriestley

Reviewed By: #blessed_reviewers, epriestley

Subscribers: Korvin, epriestley

Maniphest Tasks: T8357

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

+73 -16
+33
src/applications/calendar/controller/PhabricatorCalendarEventEditController.php
··· 17 17 $viewer = $request->getViewer(); 18 18 $user_phid = $viewer->getPHID(); 19 19 $error_name = true; 20 + $error_recurrence_end_date = true; 20 21 $error_start_date = true; 21 22 $error_end_date = true; 22 23 $validation_exception = null; 23 24 24 25 $is_recurring_id = celerity_generate_unique_node_id(); 26 + $recurrence_end_date_id = celerity_generate_unique_node_id(); 25 27 $frequency_id = celerity_generate_unique_node_id(); 26 28 $all_day_id = celerity_generate_unique_node_id(); 27 29 $start_date_id = celerity_generate_unique_node_id(); ··· 65 67 list($start_value, $end_value) = $this->getDefaultTimeValues($viewer); 66 68 } 67 69 70 + $recurrence_end_date_value = clone $end_value; 71 + $recurrence_end_date_value->setOptional(true); 68 72 69 73 $submit_label = pht('Create'); 70 74 $page_title = pht('Create Event'); ··· 138 142 $start_value = AphrontFormDateControlValue::newFromEpoch( 139 143 $viewer, 140 144 $event->getDateFrom()); 145 + $recurrence_end_date_value = id(clone $end_value) 146 + ->setOptional(true); 141 147 142 148 $submit_label = pht('Update'); 143 149 $page_title = pht('Update Event'); ··· 179 185 $end_value = AphrontFormDateControlValue::newFromRequest( 180 186 $request, 181 187 'end'); 188 + $recurrence_end_date_value = AphrontFormDateControlValue::newFromRequest( 189 + $request, 190 + 'recurrenceEndDate'); 191 + $recurrence_end_date_value->setOptional(true); 182 192 $description = $request->getStr('description'); 183 193 $subscribers = $request->getArr('subscribers'); 184 194 $edit_policy = $request->getStr('editPolicy'); ··· 213 223 ->setTransactionType( 214 224 PhabricatorCalendarEventTransaction::TYPE_FREQUENCY) 215 225 ->setNewValue(array('rule' => $frequency)); 226 + 227 + $xactions[] = id(new PhabricatorCalendarEventTransaction()) 228 + ->setTransactionType( 229 + PhabricatorCalendarEventTransaction::TYPE_RECURRENCE_END_DATE) 230 + ->setNewValue($recurrence_end_date_value); 216 231 } 217 232 218 233 $xactions[] = id(new PhabricatorCalendarEventTransaction()) ··· 290 305 PhabricatorCalendarEventTransaction::TYPE_START_DATE); 291 306 $error_end_date = $ex->getShortMessage( 292 307 PhabricatorCalendarEventTransaction::TYPE_END_DATE); 308 + $error_recurrence_end_date = $ex->getShortMessage( 309 + PhabricatorCalendarEventTransaction::TYPE_RECURRENCE_END_DATE); 293 310 294 311 $event->setViewPolicy($view_policy); 295 312 $event->setEditPolicy($edit_policy); ··· 297 314 } 298 315 299 316 $is_recurring_checkbox = null; 317 + $recurrence_end_date_control = null; 300 318 $recurrence_frequency_select = null; 301 319 302 320 $name = id(new AphrontFormTextControl()) ··· 309 327 Javelin::initBehavior('recurring-edit', array( 310 328 'isRecurring' => $is_recurring_id, 311 329 'frequency' => $frequency_id, 330 + 'recurrenceEndDate' => $recurrence_end_date_id, 312 331 )); 313 332 314 333 $is_recurring_checkbox = id(new AphrontFormCheckboxControl()) ··· 318 337 pht('Recurring Event'), 319 338 $is_recurring, 320 339 $is_recurring_id); 340 + 341 + $recurrence_end_date_control = id(new AphrontFormDateControl()) 342 + ->setUser($viewer) 343 + ->setName('recurrenceEndDate') 344 + ->setLabel(pht('Recurrence End Date')) 345 + ->setError($error_recurrence_end_date) 346 + ->setValue($recurrence_end_date_value) 347 + ->setID($recurrence_end_date_id) 348 + ->setIsTimeDisabled(true) 349 + ->setAllowNull(true) 350 + ->setIsDisabled(!$is_recurring); 321 351 322 352 $recurrence_frequency_select = id(new AphrontFormSelectControl()) 323 353 ->setName('frequency') ··· 420 450 421 451 if ($is_recurring_checkbox) { 422 452 $form->appendChild($is_recurring_checkbox); 453 + } 454 + if ($recurrence_end_date_control) { 455 + $form->appendChild($recurrence_end_date_control); 423 456 } 424 457 if ($recurrence_frequency_select) { 425 458 $form->appendControl($recurrence_frequency_select);
+8 -1
src/applications/calendar/controller/PhabricatorCalendarEventViewController.php
··· 135 135 $event, 136 136 PhabricatorPolicyCapability::CAN_EDIT); 137 137 138 - if ($event->getIsRecurring() && $event->getIsGhostEvent()) { 138 + if ($event->getIsRecurring() && $event->getInstanceOfEventPHID()) { 139 139 $index = $event->getSequenceIndex(); 140 140 141 141 $actions->addAction( ··· 231 231 $properties->addProperty( 232 232 pht('Recurs'), 233 233 ucwords(idx($event->getRecurrenceFrequency(), 'rule'))); 234 + 235 + if ($event->getRecurrenceEndDate()) { 236 + $properties->addProperty( 237 + pht('Recurrence Ends'), 238 + phabricator_datetime($event->getRecurrenceEndDate(), $viewer)); 239 + } 240 + 234 241 if ($event->getInstanceOfEventPHID()) { 235 242 $properties->addProperty( 236 243 pht('Recurrence of Event'),
+5 -3
src/applications/calendar/editor/PhabricatorCalendarEventEditor.php
··· 90 90 switch ($xaction->getTransactionType()) { 91 91 case PhabricatorCalendarEventTransaction::TYPE_RECURRING: 92 92 case PhabricatorCalendarEventTransaction::TYPE_FREQUENCY: 93 - case PhabricatorCalendarEventTransaction::TYPE_RECURRENCE_END_DATE: 94 93 case PhabricatorCalendarEventTransaction::TYPE_INSTANCE_OF_EVENT: 95 94 case PhabricatorCalendarEventTransaction::TYPE_SEQUENCE_INDEX: 96 95 case PhabricatorCalendarEventTransaction::TYPE_NAME: ··· 101 100 return $xaction->getNewValue(); 102 101 case PhabricatorCalendarEventTransaction::TYPE_ALL_DAY: 103 102 return (int)$xaction->getNewValue(); 103 + case PhabricatorCalendarEventTransaction::TYPE_RECURRENCE_END_DATE: 104 104 case PhabricatorCalendarEventTransaction::TYPE_START_DATE: 105 105 case PhabricatorCalendarEventTransaction::TYPE_END_DATE: 106 106 return $xaction->getNewValue()->getEpoch(); ··· 118 118 return $object->setIsRecurring($xaction->getNewValue()); 119 119 case PhabricatorCalendarEventTransaction::TYPE_FREQUENCY: 120 120 return $object->setRecurrenceFrequency($xaction->getNewValue()); 121 - case PhabricatorCalendarEventTransaction::TYPE_RECURRENCE_END_DATE: 122 - return $object->setRecurrenceEndDate($xaction->getNewValue()); 123 121 case PhabricatorCalendarEventTransaction::TYPE_INSTANCE_OF_EVENT: 124 122 return $object->setInstanceOfEventPHID($xaction->getNewValue()); 125 123 case PhabricatorCalendarEventTransaction::TYPE_SEQUENCE_INDEX: ··· 132 130 return; 133 131 case PhabricatorCalendarEventTransaction::TYPE_END_DATE: 134 132 $object->setDateTo($xaction->getNewValue()); 133 + return; 134 + case PhabricatorCalendarEventTransaction::TYPE_RECURRENCE_END_DATE: 135 + $object->setRecurrenceEndDate($xaction->getNewValue()); 135 136 return; 136 137 case PhabricatorCalendarEventTransaction::TYPE_DESCRIPTION: 137 138 $object->setDescription($xaction->getNewValue()); ··· 313 314 $errors[] = $error; 314 315 } 315 316 break; 317 + case PhabricatorCalendarEventTransaction::TYPE_RECURRENCE_END_DATE: 316 318 case PhabricatorCalendarEventTransaction::TYPE_START_DATE: 317 319 case PhabricatorCalendarEventTransaction::TYPE_END_DATE: 318 320 foreach ($xactions as $xaction) {
+15 -11
src/applications/calendar/query/PhabricatorCalendarEventQuery.php
··· 110 110 111 111 foreach ($events as $event) { 112 112 $sequence_start = 0; 113 - $instance_count = null; 113 + $sequence_end = null; 114 114 $duration = $event->getDateTo() - $event->getDateFrom(); 115 + $end = null; 115 116 116 117 if ($event->getIsRecurring() && !$event->getInstanceOfEventPHID()) { 117 118 $frequency = $event->getFrequencyUnit(); ··· 135 136 } 136 137 137 138 $date = $start; 138 - $start_datetime = PhabricatorTime::getDateTimeFromEpoch( 139 - $start, 140 - $viewer); 139 + $datetime = PhabricatorTime::getDateTimeFromEpoch($date, $viewer); 141 140 142 - if ($this->rangeEnd) { 141 + if (($this->rangeEnd && $event->getRecurrenceEndDate()) && 142 + $this->rangeEnd < $event->getRecurrenceEndDate()) { 143 143 $end = $this->rangeEnd; 144 - $instance_count = $sequence_start; 144 + } else if ($event->getRecurrenceEndDate()) { 145 + $end = $event->getRecurrenceEndDate(); 146 + } else if ($this->rangeEnd) { 147 + $end = $this->rangeEnd; 148 + } 145 149 150 + if ($end) { 151 + $sequence_end = $sequence_start; 146 152 while ($date < $end) { 147 - $instance_count++; 148 - $datetime = PhabricatorTime::getDateTimeFromEpoch($date, $viewer); 153 + $sequence_end++; 149 154 $datetime->modify($modify_key); 150 155 $date = $datetime->format('U'); 151 156 } 152 157 } else { 153 - $instance_count = $this->getRawResultLimit(); 158 + $sequence_end = $this->getRawResultLimit() + $sequence_start; 154 159 } 155 160 156 161 $sequence_start = max(1, $sequence_start); 157 162 158 - $max_sequence = $sequence_start + $instance_count; 159 - for ($index = $sequence_start; $index < $max_sequence; $index++) { 163 + for ($index = $sequence_start; $index < $sequence_end; $index++) { 160 164 $instance_sequence_pairs[] = array($event->getPHID(), $index); 161 165 $events[] = $event->generateNthGhost($index, $viewer); 162 166
-1
src/applications/calendar/query/PhabricatorCalendarEventSearchEngine.php
··· 373 373 $event->setDescription(pht('%s (%s)', $name_text, $status_text)); 374 374 $event->setName($status_text); 375 375 $event->setURI($status->getURI()); 376 - // $event->setEventID($status->getID()); 377 376 $event->setViewerIsInvited($viewer_is_invited); 378 377 $month_view->addEvent($event); 379 378 }
+5
src/view/form/control/AphrontFormDateControl.php
··· 23 23 return $this; 24 24 } 25 25 26 + public function setIsDisabled($is_datepicker_disabled) { 27 + $this->isDisabled = $is_datepicker_disabled; 28 + return $this; 29 + } 30 + 26 31 public function setEndDateID($value) { 27 32 $this->endDateID = $value; 28 33 return $this;
+7
webroot/rsrc/js/application/calendar/behavior-recurring-edit.js
··· 5 5 6 6 JX.behavior('recurring-edit', function(config) { 7 7 var checkbox = JX.$(config.isRecurring); 8 + 8 9 JX.DOM.listen(checkbox, 'change', null, function() { 9 10 var frequency = JX.$(config.frequency); 11 + var end_date = JX.$(config.recurrenceEndDate); 10 12 11 13 frequency.disabled = checkbox.checked ? false : true; 14 + end_date.disabled = checkbox.checked ? false : true; 15 + 16 + if (end_date.disabled) { 17 + JX.DOM.alterClass(end_date, 'datepicker-disabled', !checkbox.checked); 18 + } 12 19 }); 13 20 14 21 });