mirror of
https://we.phorge.it/source/phorge.git
synced 2024-12-27 07:50:57 +01:00
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
This commit is contained in:
parent
c83ddc3a0e
commit
95551a1a5a
7 changed files with 73 additions and 16 deletions
|
@ -17,11 +17,13 @@ final class PhabricatorCalendarEventEditController
|
||||||
$viewer = $request->getViewer();
|
$viewer = $request->getViewer();
|
||||||
$user_phid = $viewer->getPHID();
|
$user_phid = $viewer->getPHID();
|
||||||
$error_name = true;
|
$error_name = true;
|
||||||
|
$error_recurrence_end_date = true;
|
||||||
$error_start_date = true;
|
$error_start_date = true;
|
||||||
$error_end_date = true;
|
$error_end_date = true;
|
||||||
$validation_exception = null;
|
$validation_exception = null;
|
||||||
|
|
||||||
$is_recurring_id = celerity_generate_unique_node_id();
|
$is_recurring_id = celerity_generate_unique_node_id();
|
||||||
|
$recurrence_end_date_id = celerity_generate_unique_node_id();
|
||||||
$frequency_id = celerity_generate_unique_node_id();
|
$frequency_id = celerity_generate_unique_node_id();
|
||||||
$all_day_id = celerity_generate_unique_node_id();
|
$all_day_id = celerity_generate_unique_node_id();
|
||||||
$start_date_id = celerity_generate_unique_node_id();
|
$start_date_id = celerity_generate_unique_node_id();
|
||||||
|
@ -65,6 +67,8 @@ final class PhabricatorCalendarEventEditController
|
||||||
list($start_value, $end_value) = $this->getDefaultTimeValues($viewer);
|
list($start_value, $end_value) = $this->getDefaultTimeValues($viewer);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$recurrence_end_date_value = clone $end_value;
|
||||||
|
$recurrence_end_date_value->setOptional(true);
|
||||||
|
|
||||||
$submit_label = pht('Create');
|
$submit_label = pht('Create');
|
||||||
$page_title = pht('Create Event');
|
$page_title = pht('Create Event');
|
||||||
|
@ -138,6 +142,8 @@ final class PhabricatorCalendarEventEditController
|
||||||
$start_value = AphrontFormDateControlValue::newFromEpoch(
|
$start_value = AphrontFormDateControlValue::newFromEpoch(
|
||||||
$viewer,
|
$viewer,
|
||||||
$event->getDateFrom());
|
$event->getDateFrom());
|
||||||
|
$recurrence_end_date_value = id(clone $end_value)
|
||||||
|
->setOptional(true);
|
||||||
|
|
||||||
$submit_label = pht('Update');
|
$submit_label = pht('Update');
|
||||||
$page_title = pht('Update Event');
|
$page_title = pht('Update Event');
|
||||||
|
@ -179,6 +185,10 @@ final class PhabricatorCalendarEventEditController
|
||||||
$end_value = AphrontFormDateControlValue::newFromRequest(
|
$end_value = AphrontFormDateControlValue::newFromRequest(
|
||||||
$request,
|
$request,
|
||||||
'end');
|
'end');
|
||||||
|
$recurrence_end_date_value = AphrontFormDateControlValue::newFromRequest(
|
||||||
|
$request,
|
||||||
|
'recurrenceEndDate');
|
||||||
|
$recurrence_end_date_value->setOptional(true);
|
||||||
$description = $request->getStr('description');
|
$description = $request->getStr('description');
|
||||||
$subscribers = $request->getArr('subscribers');
|
$subscribers = $request->getArr('subscribers');
|
||||||
$edit_policy = $request->getStr('editPolicy');
|
$edit_policy = $request->getStr('editPolicy');
|
||||||
|
@ -213,6 +223,11 @@ final class PhabricatorCalendarEventEditController
|
||||||
->setTransactionType(
|
->setTransactionType(
|
||||||
PhabricatorCalendarEventTransaction::TYPE_FREQUENCY)
|
PhabricatorCalendarEventTransaction::TYPE_FREQUENCY)
|
||||||
->setNewValue(array('rule' => $frequency));
|
->setNewValue(array('rule' => $frequency));
|
||||||
|
|
||||||
|
$xactions[] = id(new PhabricatorCalendarEventTransaction())
|
||||||
|
->setTransactionType(
|
||||||
|
PhabricatorCalendarEventTransaction::TYPE_RECURRENCE_END_DATE)
|
||||||
|
->setNewValue($recurrence_end_date_value);
|
||||||
}
|
}
|
||||||
|
|
||||||
$xactions[] = id(new PhabricatorCalendarEventTransaction())
|
$xactions[] = id(new PhabricatorCalendarEventTransaction())
|
||||||
|
@ -290,6 +305,8 @@ final class PhabricatorCalendarEventEditController
|
||||||
PhabricatorCalendarEventTransaction::TYPE_START_DATE);
|
PhabricatorCalendarEventTransaction::TYPE_START_DATE);
|
||||||
$error_end_date = $ex->getShortMessage(
|
$error_end_date = $ex->getShortMessage(
|
||||||
PhabricatorCalendarEventTransaction::TYPE_END_DATE);
|
PhabricatorCalendarEventTransaction::TYPE_END_DATE);
|
||||||
|
$error_recurrence_end_date = $ex->getShortMessage(
|
||||||
|
PhabricatorCalendarEventTransaction::TYPE_RECURRENCE_END_DATE);
|
||||||
|
|
||||||
$event->setViewPolicy($view_policy);
|
$event->setViewPolicy($view_policy);
|
||||||
$event->setEditPolicy($edit_policy);
|
$event->setEditPolicy($edit_policy);
|
||||||
|
@ -297,6 +314,7 @@ final class PhabricatorCalendarEventEditController
|
||||||
}
|
}
|
||||||
|
|
||||||
$is_recurring_checkbox = null;
|
$is_recurring_checkbox = null;
|
||||||
|
$recurrence_end_date_control = null;
|
||||||
$recurrence_frequency_select = null;
|
$recurrence_frequency_select = null;
|
||||||
|
|
||||||
$name = id(new AphrontFormTextControl())
|
$name = id(new AphrontFormTextControl())
|
||||||
|
@ -309,6 +327,7 @@ final class PhabricatorCalendarEventEditController
|
||||||
Javelin::initBehavior('recurring-edit', array(
|
Javelin::initBehavior('recurring-edit', array(
|
||||||
'isRecurring' => $is_recurring_id,
|
'isRecurring' => $is_recurring_id,
|
||||||
'frequency' => $frequency_id,
|
'frequency' => $frequency_id,
|
||||||
|
'recurrenceEndDate' => $recurrence_end_date_id,
|
||||||
));
|
));
|
||||||
|
|
||||||
$is_recurring_checkbox = id(new AphrontFormCheckboxControl())
|
$is_recurring_checkbox = id(new AphrontFormCheckboxControl())
|
||||||
|
@ -319,6 +338,17 @@ final class PhabricatorCalendarEventEditController
|
||||||
$is_recurring,
|
$is_recurring,
|
||||||
$is_recurring_id);
|
$is_recurring_id);
|
||||||
|
|
||||||
|
$recurrence_end_date_control = id(new AphrontFormDateControl())
|
||||||
|
->setUser($viewer)
|
||||||
|
->setName('recurrenceEndDate')
|
||||||
|
->setLabel(pht('Recurrence End Date'))
|
||||||
|
->setError($error_recurrence_end_date)
|
||||||
|
->setValue($recurrence_end_date_value)
|
||||||
|
->setID($recurrence_end_date_id)
|
||||||
|
->setIsTimeDisabled(true)
|
||||||
|
->setAllowNull(true)
|
||||||
|
->setIsDisabled(!$is_recurring);
|
||||||
|
|
||||||
$recurrence_frequency_select = id(new AphrontFormSelectControl())
|
$recurrence_frequency_select = id(new AphrontFormSelectControl())
|
||||||
->setName('frequency')
|
->setName('frequency')
|
||||||
->setOptions(array(
|
->setOptions(array(
|
||||||
|
@ -421,6 +451,9 @@ final class PhabricatorCalendarEventEditController
|
||||||
if ($is_recurring_checkbox) {
|
if ($is_recurring_checkbox) {
|
||||||
$form->appendChild($is_recurring_checkbox);
|
$form->appendChild($is_recurring_checkbox);
|
||||||
}
|
}
|
||||||
|
if ($recurrence_end_date_control) {
|
||||||
|
$form->appendChild($recurrence_end_date_control);
|
||||||
|
}
|
||||||
if ($recurrence_frequency_select) {
|
if ($recurrence_frequency_select) {
|
||||||
$form->appendControl($recurrence_frequency_select);
|
$form->appendControl($recurrence_frequency_select);
|
||||||
}
|
}
|
||||||
|
|
|
@ -135,7 +135,7 @@ final class PhabricatorCalendarEventViewController
|
||||||
$event,
|
$event,
|
||||||
PhabricatorPolicyCapability::CAN_EDIT);
|
PhabricatorPolicyCapability::CAN_EDIT);
|
||||||
|
|
||||||
if ($event->getIsRecurring() && $event->getIsGhostEvent()) {
|
if ($event->getIsRecurring() && $event->getInstanceOfEventPHID()) {
|
||||||
$index = $event->getSequenceIndex();
|
$index = $event->getSequenceIndex();
|
||||||
|
|
||||||
$actions->addAction(
|
$actions->addAction(
|
||||||
|
@ -231,6 +231,13 @@ final class PhabricatorCalendarEventViewController
|
||||||
$properties->addProperty(
|
$properties->addProperty(
|
||||||
pht('Recurs'),
|
pht('Recurs'),
|
||||||
ucwords(idx($event->getRecurrenceFrequency(), 'rule')));
|
ucwords(idx($event->getRecurrenceFrequency(), 'rule')));
|
||||||
|
|
||||||
|
if ($event->getRecurrenceEndDate()) {
|
||||||
|
$properties->addProperty(
|
||||||
|
pht('Recurrence Ends'),
|
||||||
|
phabricator_datetime($event->getRecurrenceEndDate(), $viewer));
|
||||||
|
}
|
||||||
|
|
||||||
if ($event->getInstanceOfEventPHID()) {
|
if ($event->getInstanceOfEventPHID()) {
|
||||||
$properties->addProperty(
|
$properties->addProperty(
|
||||||
pht('Recurrence of Event'),
|
pht('Recurrence of Event'),
|
||||||
|
|
|
@ -90,7 +90,6 @@ final class PhabricatorCalendarEventEditor
|
||||||
switch ($xaction->getTransactionType()) {
|
switch ($xaction->getTransactionType()) {
|
||||||
case PhabricatorCalendarEventTransaction::TYPE_RECURRING:
|
case PhabricatorCalendarEventTransaction::TYPE_RECURRING:
|
||||||
case PhabricatorCalendarEventTransaction::TYPE_FREQUENCY:
|
case PhabricatorCalendarEventTransaction::TYPE_FREQUENCY:
|
||||||
case PhabricatorCalendarEventTransaction::TYPE_RECURRENCE_END_DATE:
|
|
||||||
case PhabricatorCalendarEventTransaction::TYPE_INSTANCE_OF_EVENT:
|
case PhabricatorCalendarEventTransaction::TYPE_INSTANCE_OF_EVENT:
|
||||||
case PhabricatorCalendarEventTransaction::TYPE_SEQUENCE_INDEX:
|
case PhabricatorCalendarEventTransaction::TYPE_SEQUENCE_INDEX:
|
||||||
case PhabricatorCalendarEventTransaction::TYPE_NAME:
|
case PhabricatorCalendarEventTransaction::TYPE_NAME:
|
||||||
|
@ -101,6 +100,7 @@ final class PhabricatorCalendarEventEditor
|
||||||
return $xaction->getNewValue();
|
return $xaction->getNewValue();
|
||||||
case PhabricatorCalendarEventTransaction::TYPE_ALL_DAY:
|
case PhabricatorCalendarEventTransaction::TYPE_ALL_DAY:
|
||||||
return (int)$xaction->getNewValue();
|
return (int)$xaction->getNewValue();
|
||||||
|
case PhabricatorCalendarEventTransaction::TYPE_RECURRENCE_END_DATE:
|
||||||
case PhabricatorCalendarEventTransaction::TYPE_START_DATE:
|
case PhabricatorCalendarEventTransaction::TYPE_START_DATE:
|
||||||
case PhabricatorCalendarEventTransaction::TYPE_END_DATE:
|
case PhabricatorCalendarEventTransaction::TYPE_END_DATE:
|
||||||
return $xaction->getNewValue()->getEpoch();
|
return $xaction->getNewValue()->getEpoch();
|
||||||
|
@ -118,8 +118,6 @@ final class PhabricatorCalendarEventEditor
|
||||||
return $object->setIsRecurring($xaction->getNewValue());
|
return $object->setIsRecurring($xaction->getNewValue());
|
||||||
case PhabricatorCalendarEventTransaction::TYPE_FREQUENCY:
|
case PhabricatorCalendarEventTransaction::TYPE_FREQUENCY:
|
||||||
return $object->setRecurrenceFrequency($xaction->getNewValue());
|
return $object->setRecurrenceFrequency($xaction->getNewValue());
|
||||||
case PhabricatorCalendarEventTransaction::TYPE_RECURRENCE_END_DATE:
|
|
||||||
return $object->setRecurrenceEndDate($xaction->getNewValue());
|
|
||||||
case PhabricatorCalendarEventTransaction::TYPE_INSTANCE_OF_EVENT:
|
case PhabricatorCalendarEventTransaction::TYPE_INSTANCE_OF_EVENT:
|
||||||
return $object->setInstanceOfEventPHID($xaction->getNewValue());
|
return $object->setInstanceOfEventPHID($xaction->getNewValue());
|
||||||
case PhabricatorCalendarEventTransaction::TYPE_SEQUENCE_INDEX:
|
case PhabricatorCalendarEventTransaction::TYPE_SEQUENCE_INDEX:
|
||||||
|
@ -133,6 +131,9 @@ final class PhabricatorCalendarEventEditor
|
||||||
case PhabricatorCalendarEventTransaction::TYPE_END_DATE:
|
case PhabricatorCalendarEventTransaction::TYPE_END_DATE:
|
||||||
$object->setDateTo($xaction->getNewValue());
|
$object->setDateTo($xaction->getNewValue());
|
||||||
return;
|
return;
|
||||||
|
case PhabricatorCalendarEventTransaction::TYPE_RECURRENCE_END_DATE:
|
||||||
|
$object->setRecurrenceEndDate($xaction->getNewValue());
|
||||||
|
return;
|
||||||
case PhabricatorCalendarEventTransaction::TYPE_DESCRIPTION:
|
case PhabricatorCalendarEventTransaction::TYPE_DESCRIPTION:
|
||||||
$object->setDescription($xaction->getNewValue());
|
$object->setDescription($xaction->getNewValue());
|
||||||
return;
|
return;
|
||||||
|
@ -313,6 +314,7 @@ final class PhabricatorCalendarEventEditor
|
||||||
$errors[] = $error;
|
$errors[] = $error;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
case PhabricatorCalendarEventTransaction::TYPE_RECURRENCE_END_DATE:
|
||||||
case PhabricatorCalendarEventTransaction::TYPE_START_DATE:
|
case PhabricatorCalendarEventTransaction::TYPE_START_DATE:
|
||||||
case PhabricatorCalendarEventTransaction::TYPE_END_DATE:
|
case PhabricatorCalendarEventTransaction::TYPE_END_DATE:
|
||||||
foreach ($xactions as $xaction) {
|
foreach ($xactions as $xaction) {
|
||||||
|
|
|
@ -110,8 +110,9 @@ final class PhabricatorCalendarEventQuery
|
||||||
|
|
||||||
foreach ($events as $event) {
|
foreach ($events as $event) {
|
||||||
$sequence_start = 0;
|
$sequence_start = 0;
|
||||||
$instance_count = null;
|
$sequence_end = null;
|
||||||
$duration = $event->getDateTo() - $event->getDateFrom();
|
$duration = $event->getDateTo() - $event->getDateFrom();
|
||||||
|
$end = null;
|
||||||
|
|
||||||
if ($event->getIsRecurring() && !$event->getInstanceOfEventPHID()) {
|
if ($event->getIsRecurring() && !$event->getInstanceOfEventPHID()) {
|
||||||
$frequency = $event->getFrequencyUnit();
|
$frequency = $event->getFrequencyUnit();
|
||||||
|
@ -135,28 +136,31 @@ final class PhabricatorCalendarEventQuery
|
||||||
}
|
}
|
||||||
|
|
||||||
$date = $start;
|
$date = $start;
|
||||||
$start_datetime = PhabricatorTime::getDateTimeFromEpoch(
|
$datetime = PhabricatorTime::getDateTimeFromEpoch($date, $viewer);
|
||||||
$start,
|
|
||||||
$viewer);
|
|
||||||
|
|
||||||
if ($this->rangeEnd) {
|
if (($this->rangeEnd && $event->getRecurrenceEndDate()) &&
|
||||||
|
$this->rangeEnd < $event->getRecurrenceEndDate()) {
|
||||||
$end = $this->rangeEnd;
|
$end = $this->rangeEnd;
|
||||||
$instance_count = $sequence_start;
|
} else if ($event->getRecurrenceEndDate()) {
|
||||||
|
$end = $event->getRecurrenceEndDate();
|
||||||
|
} else if ($this->rangeEnd) {
|
||||||
|
$end = $this->rangeEnd;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($end) {
|
||||||
|
$sequence_end = $sequence_start;
|
||||||
while ($date < $end) {
|
while ($date < $end) {
|
||||||
$instance_count++;
|
$sequence_end++;
|
||||||
$datetime = PhabricatorTime::getDateTimeFromEpoch($date, $viewer);
|
|
||||||
$datetime->modify($modify_key);
|
$datetime->modify($modify_key);
|
||||||
$date = $datetime->format('U');
|
$date = $datetime->format('U');
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
$instance_count = $this->getRawResultLimit();
|
$sequence_end = $this->getRawResultLimit() + $sequence_start;
|
||||||
}
|
}
|
||||||
|
|
||||||
$sequence_start = max(1, $sequence_start);
|
$sequence_start = max(1, $sequence_start);
|
||||||
|
|
||||||
$max_sequence = $sequence_start + $instance_count;
|
for ($index = $sequence_start; $index < $sequence_end; $index++) {
|
||||||
for ($index = $sequence_start; $index < $max_sequence; $index++) {
|
|
||||||
$instance_sequence_pairs[] = array($event->getPHID(), $index);
|
$instance_sequence_pairs[] = array($event->getPHID(), $index);
|
||||||
$events[] = $event->generateNthGhost($index, $viewer);
|
$events[] = $event->generateNthGhost($index, $viewer);
|
||||||
|
|
||||||
|
|
|
@ -373,7 +373,6 @@ final class PhabricatorCalendarEventSearchEngine
|
||||||
$event->setDescription(pht('%s (%s)', $name_text, $status_text));
|
$event->setDescription(pht('%s (%s)', $name_text, $status_text));
|
||||||
$event->setName($status_text);
|
$event->setName($status_text);
|
||||||
$event->setURI($status->getURI());
|
$event->setURI($status->getURI());
|
||||||
// $event->setEventID($status->getID());
|
|
||||||
$event->setViewerIsInvited($viewer_is_invited);
|
$event->setViewerIsInvited($viewer_is_invited);
|
||||||
$month_view->addEvent($event);
|
$month_view->addEvent($event);
|
||||||
}
|
}
|
||||||
|
|
|
@ -23,6 +23,11 @@ final class AphrontFormDateControl extends AphrontFormControl {
|
||||||
return $this;
|
return $this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function setIsDisabled($is_datepicker_disabled) {
|
||||||
|
$this->isDisabled = $is_datepicker_disabled;
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
public function setEndDateID($value) {
|
public function setEndDateID($value) {
|
||||||
$this->endDateID = $value;
|
$this->endDateID = $value;
|
||||||
return $this;
|
return $this;
|
||||||
|
|
|
@ -5,10 +5,17 @@
|
||||||
|
|
||||||
JX.behavior('recurring-edit', function(config) {
|
JX.behavior('recurring-edit', function(config) {
|
||||||
var checkbox = JX.$(config.isRecurring);
|
var checkbox = JX.$(config.isRecurring);
|
||||||
|
|
||||||
JX.DOM.listen(checkbox, 'change', null, function() {
|
JX.DOM.listen(checkbox, 'change', null, function() {
|
||||||
var frequency = JX.$(config.frequency);
|
var frequency = JX.$(config.frequency);
|
||||||
|
var end_date = JX.$(config.recurrenceEndDate);
|
||||||
|
|
||||||
frequency.disabled = checkbox.checked ? false : true;
|
frequency.disabled = checkbox.checked ? false : true;
|
||||||
|
end_date.disabled = checkbox.checked ? false : true;
|
||||||
|
|
||||||
|
if (end_date.disabled) {
|
||||||
|
JX.DOM.alterClass(end_date, 'datepicker-disabled', !checkbox.checked);
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
Loading…
Reference in a new issue