mirror of
https://we.phorge.it/source/phorge.git
synced 2024-11-26 08:42:41 +01:00
DRAFT Add db columns for recurring events
Summary: Ref T2896, DRAFT Add db columns for recurring events Test Plan: Open event, confirm it still works. Reviewers: chad, #blessed_reviewers, epriestley Reviewed By: #blessed_reviewers, epriestley Subscribers: btrahan, Korvin, epriestley Maniphest Tasks: T2896 Differential Revision: https://secure.phabricator.com/D13039
This commit is contained in:
parent
1aa8bc319b
commit
59f0e8f950
13 changed files with 354 additions and 30 deletions
|
@ -7,7 +7,7 @@
|
||||||
*/
|
*/
|
||||||
return array(
|
return array(
|
||||||
'names' => array(
|
'names' => array(
|
||||||
'core.pkg.css' => '68d4f4fb',
|
'core.pkg.css' => 'e2460e8f',
|
||||||
'core.pkg.js' => '3bbe23c6',
|
'core.pkg.js' => '3bbe23c6',
|
||||||
'darkconsole.pkg.js' => 'e7393ebb',
|
'darkconsole.pkg.js' => 'e7393ebb',
|
||||||
'differential.pkg.css' => '30602b8c',
|
'differential.pkg.css' => '30602b8c',
|
||||||
|
@ -135,7 +135,7 @@ return array(
|
||||||
'rsrc/css/phui/phui-feed-story.css' => 'c9f3a0b5',
|
'rsrc/css/phui/phui-feed-story.css' => 'c9f3a0b5',
|
||||||
'rsrc/css/phui/phui-fontkit.css' => 'dd8ddf27',
|
'rsrc/css/phui/phui-fontkit.css' => 'dd8ddf27',
|
||||||
'rsrc/css/phui/phui-form-view.css' => '808329f2',
|
'rsrc/css/phui/phui-form-view.css' => '808329f2',
|
||||||
'rsrc/css/phui/phui-form.css' => 'f535f938',
|
'rsrc/css/phui/phui-form.css' => '25876baf',
|
||||||
'rsrc/css/phui/phui-header-view.css' => '75aaf372',
|
'rsrc/css/phui/phui-header-view.css' => '75aaf372',
|
||||||
'rsrc/css/phui/phui-icon.css' => 'bc766998',
|
'rsrc/css/phui/phui-icon.css' => 'bc766998',
|
||||||
'rsrc/css/phui/phui-image-mask.css' => '5a8b09c8',
|
'rsrc/css/phui/phui-image-mask.css' => '5a8b09c8',
|
||||||
|
@ -333,6 +333,7 @@ return array(
|
||||||
'rsrc/js/application/auth/behavior-persona-login.js' => '9414ff18',
|
'rsrc/js/application/auth/behavior-persona-login.js' => '9414ff18',
|
||||||
'rsrc/js/application/calendar/behavior-day-view.js' => '5c46cff2',
|
'rsrc/js/application/calendar/behavior-day-view.js' => '5c46cff2',
|
||||||
'rsrc/js/application/calendar/behavior-event-all-day.js' => '38dcf3c8',
|
'rsrc/js/application/calendar/behavior-event-all-day.js' => '38dcf3c8',
|
||||||
|
'rsrc/js/application/calendar/behavior-recurring-edit.js' => '85c73ceb',
|
||||||
'rsrc/js/application/config/behavior-reorder-fields.js' => 'b6993408',
|
'rsrc/js/application/config/behavior-reorder-fields.js' => 'b6993408',
|
||||||
'rsrc/js/application/conpherence/ConpherenceThreadManager.js' => '01774ab2',
|
'rsrc/js/application/conpherence/ConpherenceThreadManager.js' => '01774ab2',
|
||||||
'rsrc/js/application/conpherence/behavior-drag-and-drop-photo.js' => 'cf86d16a',
|
'rsrc/js/application/conpherence/behavior-drag-and-drop-photo.js' => 'cf86d16a',
|
||||||
|
@ -629,6 +630,7 @@ return array(
|
||||||
'javelin-behavior-project-boards' => 'ba4fa35c',
|
'javelin-behavior-project-boards' => 'ba4fa35c',
|
||||||
'javelin-behavior-project-create' => '065227cc',
|
'javelin-behavior-project-create' => '065227cc',
|
||||||
'javelin-behavior-quicksand-blacklist' => '7927a7d3',
|
'javelin-behavior-quicksand-blacklist' => '7927a7d3',
|
||||||
|
'javelin-behavior-recurring-edit' => '85c73ceb',
|
||||||
'javelin-behavior-refresh-csrf' => '7814b593',
|
'javelin-behavior-refresh-csrf' => '7814b593',
|
||||||
'javelin-behavior-releeph-preview-branch' => 'b2b4fbaf',
|
'javelin-behavior-releeph-preview-branch' => 'b2b4fbaf',
|
||||||
'javelin-behavior-releeph-request-state-change' => 'a0b57eb8',
|
'javelin-behavior-releeph-request-state-change' => 'a0b57eb8',
|
||||||
|
@ -775,7 +777,7 @@ return array(
|
||||||
'phui-feed-story-css' => 'c9f3a0b5',
|
'phui-feed-story-css' => 'c9f3a0b5',
|
||||||
'phui-font-icon-base-css' => '3dad2ae3',
|
'phui-font-icon-base-css' => '3dad2ae3',
|
||||||
'phui-fontkit-css' => 'dd8ddf27',
|
'phui-fontkit-css' => 'dd8ddf27',
|
||||||
'phui-form-css' => 'f535f938',
|
'phui-form-css' => '25876baf',
|
||||||
'phui-form-view-css' => '808329f2',
|
'phui-form-view-css' => '808329f2',
|
||||||
'phui-header-view-css' => '75aaf372',
|
'phui-header-view-css' => '75aaf372',
|
||||||
'phui-icon-view-css' => 'bc766998',
|
'phui-icon-view-css' => 'bc766998',
|
||||||
|
|
|
@ -0,0 +1,17 @@
|
||||||
|
ALTER TABLE {$NAMESPACE}_calendar.calendar_event
|
||||||
|
ADD isRecurring BOOL NOT NULL;
|
||||||
|
|
||||||
|
ALTER TABLE {$NAMESPACE}_calendar.calendar_event
|
||||||
|
ADD recurrenceFrequency LONGTEXT COLLATE {$COLLATE_TEXT} NOT NULL;
|
||||||
|
|
||||||
|
ALTER TABLE {$NAMESPACE}_calendar.calendar_event
|
||||||
|
ADD recurrenceEndDate INT UNSIGNED;
|
||||||
|
|
||||||
|
ALTER TABLE {$NAMESPACE}_calendar.calendar_event
|
||||||
|
ADD instanceOfEventPHID varbinary(64);
|
||||||
|
|
||||||
|
ALTER TABLE {$NAMESPACE}_calendar.calendar_event
|
||||||
|
ADD sequenceIndex INT UNSIGNED;
|
||||||
|
|
||||||
|
UPDATE {$NAMESPACE}_calendar.calendar_event
|
||||||
|
SET recurrenceFrequency = '[]' WHERE recurrenceFrequency = '';
|
|
@ -40,7 +40,8 @@ final class PhabricatorCalendarApplication extends PhabricatorApplication {
|
||||||
|
|
||||||
public function getRoutes() {
|
public function getRoutes() {
|
||||||
return array(
|
return array(
|
||||||
'/E(?P<id>[1-9]\d*)' => 'PhabricatorCalendarEventViewController',
|
'/E(?P<id>[1-9]\d*)(?:/(?P<sequence>\d+))?'
|
||||||
|
=> 'PhabricatorCalendarEventViewController',
|
||||||
'/calendar/' => array(
|
'/calendar/' => array(
|
||||||
'(?:query/(?P<queryKey>[^/]+)/(?:(?P<year>\d+)/'.
|
'(?:query/(?P<queryKey>[^/]+)/(?:(?P<year>\d+)/'.
|
||||||
'(?P<month>\d+)/)?(?:(?P<day>\d+)/)?)?'
|
'(?P<month>\d+)/)?(?:(?P<day>\d+)/)?)?'
|
||||||
|
|
|
@ -21,9 +21,11 @@ final class PhabricatorCalendarEventEditController
|
||||||
$error_end_date = true;
|
$error_end_date = true;
|
||||||
$validation_exception = null;
|
$validation_exception = null;
|
||||||
|
|
||||||
|
$is_recurring_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();
|
||||||
$end_date_id = null;
|
$end_date_id = celerity_generate_unique_node_id();
|
||||||
|
|
||||||
$next_workflow = $request->getStr('next');
|
$next_workflow = $request->getStr('next');
|
||||||
$uri_query = $request->getStr('query');
|
$uri_query = $request->getStr('query');
|
||||||
|
@ -70,7 +72,6 @@ final class PhabricatorCalendarEventEditController
|
||||||
$subscribers = array();
|
$subscribers = array();
|
||||||
$invitees = array($user_phid);
|
$invitees = array($user_phid);
|
||||||
$cancel_uri = $this->getApplicationURI();
|
$cancel_uri = $this->getApplicationURI();
|
||||||
$end_date_id = celerity_generate_unique_node_id();
|
|
||||||
} else {
|
} else {
|
||||||
$event = id(new PhabricatorCalendarEventQuery())
|
$event = id(new PhabricatorCalendarEventQuery())
|
||||||
->setViewer($viewer)
|
->setViewer($viewer)
|
||||||
|
@ -113,6 +114,8 @@ final class PhabricatorCalendarEventEditController
|
||||||
$name = $event->getName();
|
$name = $event->getName();
|
||||||
$description = $event->getDescription();
|
$description = $event->getDescription();
|
||||||
$is_all_day = $event->getIsAllDay();
|
$is_all_day = $event->getIsAllDay();
|
||||||
|
$is_recurring = $event->getIsRecurring();
|
||||||
|
$frequency = idx($event->getRecurrenceFrequency(), 'rule');
|
||||||
$icon = $event->getIcon();
|
$icon = $event->getIcon();
|
||||||
|
|
||||||
$current_policies = id(new PhabricatorPolicyQuery())
|
$current_policies = id(new PhabricatorPolicyQuery())
|
||||||
|
@ -134,6 +137,8 @@ final class PhabricatorCalendarEventEditController
|
||||||
$subscribers = $request->getArr('subscribers');
|
$subscribers = $request->getArr('subscribers');
|
||||||
$edit_policy = $request->getStr('editPolicy');
|
$edit_policy = $request->getStr('editPolicy');
|
||||||
$view_policy = $request->getStr('viewPolicy');
|
$view_policy = $request->getStr('viewPolicy');
|
||||||
|
$is_recurring = $request->getStr('isRecurring') ? 1 : 0;
|
||||||
|
$frequency = $request->getStr('frequency');
|
||||||
$is_all_day = $request->getStr('isAllDay');
|
$is_all_day = $request->getStr('isAllDay');
|
||||||
$icon = $request->getStr('icon');
|
$icon = $request->getStr('icon');
|
||||||
|
|
||||||
|
@ -152,6 +157,16 @@ final class PhabricatorCalendarEventEditController
|
||||||
PhabricatorCalendarEventTransaction::TYPE_NAME)
|
PhabricatorCalendarEventTransaction::TYPE_NAME)
|
||||||
->setNewValue($name);
|
->setNewValue($name);
|
||||||
|
|
||||||
|
$xactions[] = id(new PhabricatorCalendarEventTransaction())
|
||||||
|
->setTransactionType(
|
||||||
|
PhabricatorCalendarEventTransaction::TYPE_RECURRING)
|
||||||
|
->setNewValue($is_recurring);
|
||||||
|
|
||||||
|
$xactions[] = id(new PhabricatorCalendarEventTransaction())
|
||||||
|
->setTransactionType(
|
||||||
|
PhabricatorCalendarEventTransaction::TYPE_FREQUENCY)
|
||||||
|
->setNewValue(array('rule' => $frequency));
|
||||||
|
|
||||||
$xactions[] = id(new PhabricatorCalendarEventTransaction())
|
$xactions[] = id(new PhabricatorCalendarEventTransaction())
|
||||||
->setTransactionType(
|
->setTransactionType(
|
||||||
PhabricatorCalendarEventTransaction::TYPE_ALL_DAY)
|
PhabricatorCalendarEventTransaction::TYPE_ALL_DAY)
|
||||||
|
@ -233,18 +248,44 @@ final class PhabricatorCalendarEventEditController
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Javelin::initBehavior('event-all-day', array(
|
|
||||||
'allDayID' => $all_day_id,
|
|
||||||
'startDateID' => $start_date_id,
|
|
||||||
'endDateID' => $end_date_id,
|
|
||||||
));
|
|
||||||
|
|
||||||
$name = id(new AphrontFormTextControl())
|
$name = id(new AphrontFormTextControl())
|
||||||
->setLabel(pht('Name'))
|
->setLabel(pht('Name'))
|
||||||
->setName('name')
|
->setName('name')
|
||||||
->setValue($name)
|
->setValue($name)
|
||||||
->setError($error_name);
|
->setError($error_name);
|
||||||
|
|
||||||
|
Javelin::initBehavior('recurring-edit', array(
|
||||||
|
'isRecurring' => $is_recurring_id,
|
||||||
|
'frequency' => $frequency_id,
|
||||||
|
));
|
||||||
|
|
||||||
|
$is_recurring_checkbox = id(new AphrontFormCheckboxControl())
|
||||||
|
->addCheckbox(
|
||||||
|
'isRecurring',
|
||||||
|
1,
|
||||||
|
pht('Recurring Event'),
|
||||||
|
$is_recurring,
|
||||||
|
$is_recurring_id);
|
||||||
|
|
||||||
|
$recurrence_frequency_select = id(new AphrontFormSelectControl())
|
||||||
|
->setName('frequency')
|
||||||
|
->setOptions(array(
|
||||||
|
'daily' => pht('Daily'),
|
||||||
|
'weekly' => pht('Weekly'),
|
||||||
|
'monthly' => pht('Monthly'),
|
||||||
|
'yearly' => pht('Yearly'),
|
||||||
|
))
|
||||||
|
->setValue($frequency)
|
||||||
|
->setLabel(pht('Recurring Event Frequency'))
|
||||||
|
->setID($frequency_id)
|
||||||
|
->setDisabled(!$is_recurring);
|
||||||
|
|
||||||
|
Javelin::initBehavior('event-all-day', array(
|
||||||
|
'allDayID' => $all_day_id,
|
||||||
|
'startDateID' => $start_date_id,
|
||||||
|
'endDateID' => $end_date_id,
|
||||||
|
));
|
||||||
|
|
||||||
$all_day_checkbox = id(new AphrontFormCheckboxControl())
|
$all_day_checkbox = id(new AphrontFormCheckboxControl())
|
||||||
->addCheckbox(
|
->addCheckbox(
|
||||||
'isAllDay',
|
'isAllDay',
|
||||||
|
@ -323,6 +364,8 @@ final class PhabricatorCalendarEventEditController
|
||||||
->addHiddenInput('query', $uri_query)
|
->addHiddenInput('query', $uri_query)
|
||||||
->setUser($viewer)
|
->setUser($viewer)
|
||||||
->appendChild($name)
|
->appendChild($name)
|
||||||
|
->appendChild($is_recurring_checkbox)
|
||||||
|
->appendChild($recurrence_frequency_select)
|
||||||
->appendChild($all_day_checkbox)
|
->appendChild($all_day_checkbox)
|
||||||
->appendChild($start_control)
|
->appendChild($start_control)
|
||||||
->appendChild($end_control)
|
->appendChild($end_control)
|
||||||
|
|
|
@ -17,6 +17,8 @@ final class PhabricatorCalendarEventViewController
|
||||||
$request = $this->getRequest();
|
$request = $this->getRequest();
|
||||||
$viewer = $request->getUser();
|
$viewer = $request->getUser();
|
||||||
|
|
||||||
|
$sequence = $request->getURIData('sequence');
|
||||||
|
|
||||||
$event = id(new PhabricatorCalendarEventQuery())
|
$event = id(new PhabricatorCalendarEventQuery())
|
||||||
->setViewer($viewer)
|
->setViewer($viewer)
|
||||||
->withIDs(array($this->id))
|
->withIDs(array($this->id))
|
||||||
|
@ -25,6 +27,12 @@ final class PhabricatorCalendarEventViewController
|
||||||
return new Aphront404Response();
|
return new Aphront404Response();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ($sequence && $event->getIsRecurring()) {
|
||||||
|
$event = $event->generateNthGhost($sequence, $viewer);
|
||||||
|
} else if ($sequence) {
|
||||||
|
return new Aphront404Response();
|
||||||
|
}
|
||||||
|
|
||||||
$title = 'E'.$event->getID();
|
$title = 'E'.$event->getID();
|
||||||
$page_title = $title.' '.$event->getName();
|
$page_title = $title.' '.$event->getName();
|
||||||
$crumbs = $this->buildApplicationCrumbs();
|
$crumbs = $this->buildApplicationCrumbs();
|
||||||
|
@ -127,13 +135,15 @@ final class PhabricatorCalendarEventViewController
|
||||||
$event,
|
$event,
|
||||||
PhabricatorPolicyCapability::CAN_EDIT);
|
PhabricatorPolicyCapability::CAN_EDIT);
|
||||||
|
|
||||||
$actions->addAction(
|
if (!$event->getIsGhostEvent()) {
|
||||||
id(new PhabricatorActionView())
|
$actions->addAction(
|
||||||
->setName(pht('Edit Event'))
|
id(new PhabricatorActionView())
|
||||||
->setIcon('fa-pencil')
|
->setName(pht('Edit Event'))
|
||||||
->setHref($this->getApplicationURI("event/edit/{$id}/"))
|
->setIcon('fa-pencil')
|
||||||
->setDisabled(!$can_edit)
|
->setHref($this->getApplicationURI("event/edit/{$id}/"))
|
||||||
->setWorkflow(!$can_edit));
|
->setDisabled(!$can_edit)
|
||||||
|
->setWorkflow(!$can_edit));
|
||||||
|
}
|
||||||
|
|
||||||
if ($is_attending) {
|
if ($is_attending) {
|
||||||
$actions->addAction(
|
$actions->addAction(
|
||||||
|
@ -205,6 +215,12 @@ final class PhabricatorCalendarEventViewController
|
||||||
phabricator_datetime($event->getDateTo(), $viewer));
|
phabricator_datetime($event->getDateTo(), $viewer));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ($event->getIsRecurring()) {
|
||||||
|
$properties->addProperty(
|
||||||
|
pht('Recurs'),
|
||||||
|
idx($event->getRecurrenceFrequency(), 'rule'));
|
||||||
|
}
|
||||||
|
|
||||||
$properties->addProperty(
|
$properties->addProperty(
|
||||||
pht('Host'),
|
pht('Host'),
|
||||||
$viewer->renderHandle($event->getUserPHID()));
|
$viewer->renderHandle($event->getUserPHID()));
|
||||||
|
|
|
@ -23,6 +23,12 @@ final class PhabricatorCalendarEventEditor
|
||||||
$types[] = PhabricatorCalendarEventTransaction::TYPE_ALL_DAY;
|
$types[] = PhabricatorCalendarEventTransaction::TYPE_ALL_DAY;
|
||||||
$types[] = PhabricatorCalendarEventTransaction::TYPE_ICON;
|
$types[] = PhabricatorCalendarEventTransaction::TYPE_ICON;
|
||||||
|
|
||||||
|
$types[] = PhabricatorCalendarEventTransaction::TYPE_RECURRING;
|
||||||
|
$types[] = PhabricatorCalendarEventTransaction::TYPE_FREQUENCY;
|
||||||
|
$types[] = PhabricatorCalendarEventTransaction::TYPE_RECURRENCE_END_DATE;
|
||||||
|
$types[] = PhabricatorCalendarEventTransaction::TYPE_INSTANCE_OF_EVENT;
|
||||||
|
$types[] = PhabricatorCalendarEventTransaction::TYPE_SEQUENCE_INDEX;
|
||||||
|
|
||||||
$types[] = PhabricatorTransactions::TYPE_COMMENT;
|
$types[] = PhabricatorTransactions::TYPE_COMMENT;
|
||||||
$types[] = PhabricatorTransactions::TYPE_VIEW_POLICY;
|
$types[] = PhabricatorTransactions::TYPE_VIEW_POLICY;
|
||||||
$types[] = PhabricatorTransactions::TYPE_EDIT_POLICY;
|
$types[] = PhabricatorTransactions::TYPE_EDIT_POLICY;
|
||||||
|
@ -34,6 +40,16 @@ final class PhabricatorCalendarEventEditor
|
||||||
PhabricatorLiskDAO $object,
|
PhabricatorLiskDAO $object,
|
||||||
PhabricatorApplicationTransaction $xaction) {
|
PhabricatorApplicationTransaction $xaction) {
|
||||||
switch ($xaction->getTransactionType()) {
|
switch ($xaction->getTransactionType()) {
|
||||||
|
case PhabricatorCalendarEventTransaction::TYPE_RECURRING:
|
||||||
|
return $object->getIsRecurring();
|
||||||
|
case PhabricatorCalendarEventTransaction::TYPE_FREQUENCY:
|
||||||
|
return $object->getRecurrenceFrequency();
|
||||||
|
case PhabricatorCalendarEventTransaction::TYPE_RECURRENCE_END_DATE:
|
||||||
|
return $object->getRecurrenceEndDate();
|
||||||
|
case PhabricatorCalendarEventTransaction::TYPE_INSTANCE_OF_EVENT:
|
||||||
|
return $object->getInstanceOfEventPHID();
|
||||||
|
case PhabricatorCalendarEventTransaction::TYPE_SEQUENCE_INDEX:
|
||||||
|
return $object->getSequenceIndex();
|
||||||
case PhabricatorCalendarEventTransaction::TYPE_NAME:
|
case PhabricatorCalendarEventTransaction::TYPE_NAME:
|
||||||
return $object->getName();
|
return $object->getName();
|
||||||
case PhabricatorCalendarEventTransaction::TYPE_START_DATE:
|
case PhabricatorCalendarEventTransaction::TYPE_START_DATE:
|
||||||
|
@ -72,6 +88,11 @@ final class PhabricatorCalendarEventEditor
|
||||||
PhabricatorLiskDAO $object,
|
PhabricatorLiskDAO $object,
|
||||||
PhabricatorApplicationTransaction $xaction) {
|
PhabricatorApplicationTransaction $xaction) {
|
||||||
switch ($xaction->getTransactionType()) {
|
switch ($xaction->getTransactionType()) {
|
||||||
|
case PhabricatorCalendarEventTransaction::TYPE_RECURRING:
|
||||||
|
case PhabricatorCalendarEventTransaction::TYPE_FREQUENCY:
|
||||||
|
case PhabricatorCalendarEventTransaction::TYPE_RECURRENCE_END_DATE:
|
||||||
|
case PhabricatorCalendarEventTransaction::TYPE_INSTANCE_OF_EVENT:
|
||||||
|
case PhabricatorCalendarEventTransaction::TYPE_SEQUENCE_INDEX:
|
||||||
case PhabricatorCalendarEventTransaction::TYPE_NAME:
|
case PhabricatorCalendarEventTransaction::TYPE_NAME:
|
||||||
case PhabricatorCalendarEventTransaction::TYPE_DESCRIPTION:
|
case PhabricatorCalendarEventTransaction::TYPE_DESCRIPTION:
|
||||||
case PhabricatorCalendarEventTransaction::TYPE_CANCEL:
|
case PhabricatorCalendarEventTransaction::TYPE_CANCEL:
|
||||||
|
@ -93,6 +114,16 @@ final class PhabricatorCalendarEventEditor
|
||||||
PhabricatorApplicationTransaction $xaction) {
|
PhabricatorApplicationTransaction $xaction) {
|
||||||
|
|
||||||
switch ($xaction->getTransactionType()) {
|
switch ($xaction->getTransactionType()) {
|
||||||
|
case PhabricatorCalendarEventTransaction::TYPE_RECURRING:
|
||||||
|
return $object->setIsRecurring($xaction->getNewValue());
|
||||||
|
case PhabricatorCalendarEventTransaction::TYPE_FREQUENCY:
|
||||||
|
return $object->setRecurrenceFrequency($xaction->getNewValue());
|
||||||
|
case PhabricatorCalendarEventTransaction::TYPE_RECURRENCE_END_DATE:
|
||||||
|
return $object->setRecurrenceEndDate($xaction->getNewValue());
|
||||||
|
case PhabricatorCalendarEventTransaction::TYPE_INSTANCE_OF_EVENT:
|
||||||
|
return $object->setInstanceOfEventPHID($xaction->getNewValue());
|
||||||
|
case PhabricatorCalendarEventTransaction::TYPE_SEQUENCE_INDEX:
|
||||||
|
return $object->setSequenceIndex($xaction->getNewValue());
|
||||||
case PhabricatorCalendarEventTransaction::TYPE_NAME:
|
case PhabricatorCalendarEventTransaction::TYPE_NAME:
|
||||||
$object->setName($xaction->getNewValue());
|
$object->setName($xaction->getNewValue());
|
||||||
return;
|
return;
|
||||||
|
@ -126,6 +157,11 @@ final class PhabricatorCalendarEventEditor
|
||||||
PhabricatorApplicationTransaction $xaction) {
|
PhabricatorApplicationTransaction $xaction) {
|
||||||
|
|
||||||
switch ($xaction->getTransactionType()) {
|
switch ($xaction->getTransactionType()) {
|
||||||
|
case PhabricatorCalendarEventTransaction::TYPE_RECURRING:
|
||||||
|
case PhabricatorCalendarEventTransaction::TYPE_FREQUENCY:
|
||||||
|
case PhabricatorCalendarEventTransaction::TYPE_RECURRENCE_END_DATE:
|
||||||
|
case PhabricatorCalendarEventTransaction::TYPE_INSTANCE_OF_EVENT:
|
||||||
|
case PhabricatorCalendarEventTransaction::TYPE_SEQUENCE_INDEX:
|
||||||
case PhabricatorCalendarEventTransaction::TYPE_NAME:
|
case PhabricatorCalendarEventTransaction::TYPE_NAME:
|
||||||
case PhabricatorCalendarEventTransaction::TYPE_START_DATE:
|
case PhabricatorCalendarEventTransaction::TYPE_START_DATE:
|
||||||
case PhabricatorCalendarEventTransaction::TYPE_END_DATE:
|
case PhabricatorCalendarEventTransaction::TYPE_END_DATE:
|
||||||
|
@ -181,6 +217,11 @@ final class PhabricatorCalendarEventEditor
|
||||||
switch ($xaction->getTransactionType()) {
|
switch ($xaction->getTransactionType()) {
|
||||||
case PhabricatorCalendarEventTransaction::TYPE_ICON:
|
case PhabricatorCalendarEventTransaction::TYPE_ICON:
|
||||||
break;
|
break;
|
||||||
|
case PhabricatorCalendarEventTransaction::TYPE_RECURRING:
|
||||||
|
case PhabricatorCalendarEventTransaction::TYPE_FREQUENCY:
|
||||||
|
case PhabricatorCalendarEventTransaction::TYPE_RECURRENCE_END_DATE:
|
||||||
|
case PhabricatorCalendarEventTransaction::TYPE_INSTANCE_OF_EVENT:
|
||||||
|
case PhabricatorCalendarEventTransaction::TYPE_SEQUENCE_INDEX:
|
||||||
case PhabricatorCalendarEventTransaction::TYPE_START_DATE:
|
case PhabricatorCalendarEventTransaction::TYPE_START_DATE:
|
||||||
case PhabricatorCalendarEventTransaction::TYPE_END_DATE:
|
case PhabricatorCalendarEventTransaction::TYPE_END_DATE:
|
||||||
case PhabricatorCalendarEventTransaction::TYPE_CANCEL:
|
case PhabricatorCalendarEventTransaction::TYPE_CANCEL:
|
||||||
|
|
|
@ -11,6 +11,13 @@ final class PhabricatorCalendarEventQuery
|
||||||
private $creatorPHIDs;
|
private $creatorPHIDs;
|
||||||
private $isCancelled;
|
private $isCancelled;
|
||||||
|
|
||||||
|
private $generateGhosts = false;
|
||||||
|
|
||||||
|
public function setGenerateGhosts($generate_ghosts) {
|
||||||
|
$this->generateGhosts = $generate_ghosts;
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
public function withIDs(array $ids) {
|
public function withIDs(array $ids) {
|
||||||
$this->ids = $ids;
|
$this->ids = $ids;
|
||||||
return $this;
|
return $this;
|
||||||
|
@ -69,6 +76,7 @@ final class PhabricatorCalendarEventQuery
|
||||||
protected function loadPage() {
|
protected function loadPage() {
|
||||||
$table = new PhabricatorCalendarEvent();
|
$table = new PhabricatorCalendarEvent();
|
||||||
$conn_r = $table->establishConnection('r');
|
$conn_r = $table->establishConnection('r');
|
||||||
|
$viewer = $this->getViewer();
|
||||||
|
|
||||||
$data = queryfx_all(
|
$data = queryfx_all(
|
||||||
$conn_r,
|
$conn_r,
|
||||||
|
@ -86,6 +94,63 @@ final class PhabricatorCalendarEventQuery
|
||||||
$event->applyViewerTimezone($this->getViewer());
|
$event->applyViewerTimezone($this->getViewer());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!$this->generateGhosts) {
|
||||||
|
return $events;
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach ($events as $event) {
|
||||||
|
$sequence_start = 0;
|
||||||
|
$instance_count = null;
|
||||||
|
|
||||||
|
if ($event->getIsRecurring()) {
|
||||||
|
$frequency = $event->getFrequencyUnit();
|
||||||
|
$modify_key = '+1 '.$frequency;
|
||||||
|
|
||||||
|
if ($this->rangeBegin && $this->rangeBegin > $event->getDateFrom()) {
|
||||||
|
$max_date = $this->rangeBegin;
|
||||||
|
$date = $event->getDateFrom();
|
||||||
|
$datetime = PhabricatorTime::getDateTimeFromEpoch($date, $viewer);
|
||||||
|
|
||||||
|
while ($date < $max_date) {
|
||||||
|
// TODO: optimize this to not loop through all off-screen events
|
||||||
|
$sequence_start++;
|
||||||
|
$datetime = PhabricatorTime::getDateTimeFromEpoch($date, $viewer);
|
||||||
|
$date = $datetime->modify($modify_key)->format('U');
|
||||||
|
}
|
||||||
|
|
||||||
|
$start = $this->rangeBegin;
|
||||||
|
} else {
|
||||||
|
$start = $event->getDateFrom();
|
||||||
|
}
|
||||||
|
|
||||||
|
$date = $start;
|
||||||
|
$start_datetime = PhabricatorTime::getDateTimeFromEpoch(
|
||||||
|
$start,
|
||||||
|
$viewer);
|
||||||
|
|
||||||
|
if ($this->rangeEnd) {
|
||||||
|
$end = $this->rangeEnd;
|
||||||
|
$instance_count = $sequence_start;
|
||||||
|
|
||||||
|
while ($date < $end) {
|
||||||
|
$instance_count++;
|
||||||
|
$datetime = PhabricatorTime::getDateTimeFromEpoch($date, $viewer);
|
||||||
|
$datetime->modify($modify_key);
|
||||||
|
$date = $datetime->format('U');
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
$instance_count = $this->getRawResultLimit();
|
||||||
|
}
|
||||||
|
|
||||||
|
$sequence_start = max(1, $sequence_start);
|
||||||
|
|
||||||
|
$max_sequence = $sequence_start + $instance_count;
|
||||||
|
for ($index = $sequence_start; $index < $max_sequence; $index++) {
|
||||||
|
$events[] = $event->generateNthGhost($index, $viewer);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return $events;
|
return $events;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -122,7 +187,7 @@ final class PhabricatorCalendarEventQuery
|
||||||
if ($this->rangeBegin) {
|
if ($this->rangeBegin) {
|
||||||
$where[] = qsprintf(
|
$where[] = qsprintf(
|
||||||
$conn_r,
|
$conn_r,
|
||||||
'event.dateTo >= %d',
|
'event.dateTo >= %d OR event.isRecurring = 1',
|
||||||
$this->rangeBegin);
|
$this->rangeBegin);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -50,7 +50,8 @@ final class PhabricatorCalendarEventSearchEngine
|
||||||
}
|
}
|
||||||
|
|
||||||
public function buildQueryFromSavedQuery(PhabricatorSavedQuery $saved) {
|
public function buildQueryFromSavedQuery(PhabricatorSavedQuery $saved) {
|
||||||
$query = id(new PhabricatorCalendarEventQuery());
|
$query = id(new PhabricatorCalendarEventQuery())
|
||||||
|
->setGenerateGhosts(true);
|
||||||
$viewer = $this->requireViewer();
|
$viewer = $this->requireViewer();
|
||||||
$timezone = new DateTimeZone($viewer->getTimezoneIdentifier());
|
$timezone = new DateTimeZone($viewer->getTimezoneIdentifier());
|
||||||
|
|
||||||
|
@ -132,7 +133,8 @@ final class PhabricatorCalendarEventSearchEngine
|
||||||
$query->withCreatorPHIDs($creator_phids);
|
$query->withCreatorPHIDs($creator_phids);
|
||||||
}
|
}
|
||||||
|
|
||||||
$is_cancelled = $saved->getParameter('isCancelled');
|
$is_cancelled = $saved->getParameter('isCancelled', 'active');
|
||||||
|
|
||||||
switch ($is_cancelled) {
|
switch ($is_cancelled) {
|
||||||
case 'active':
|
case 'active':
|
||||||
$query->withIsCancelled(false);
|
$query->withIsCancelled(false);
|
||||||
|
@ -305,14 +307,14 @@ final class PhabricatorCalendarEventSearchEngine
|
||||||
$viewer = $this->requireViewer();
|
$viewer = $this->requireViewer();
|
||||||
$list = new PHUIObjectItemListView();
|
$list = new PHUIObjectItemListView();
|
||||||
foreach ($events as $event) {
|
foreach ($events as $event) {
|
||||||
$href = '/E'.$event->getID();
|
// $href = '/E'.$event->getID();
|
||||||
$from = phabricator_datetime($event->getDateFrom(), $viewer);
|
$from = phabricator_datetime($event->getDateFrom(), $viewer);
|
||||||
$to = phabricator_datetime($event->getDateTo(), $viewer);
|
$to = phabricator_datetime($event->getDateTo(), $viewer);
|
||||||
$creator_handle = $handles[$event->getUserPHID()];
|
$creator_handle = $handles[$event->getUserPHID()];
|
||||||
|
|
||||||
$item = id(new PHUIObjectItemView())
|
$item = id(new PHUIObjectItemView())
|
||||||
->setHeader($event->getName())
|
->setHeader($event->getName())
|
||||||
->setHref($href)
|
->setHref($event->getURI())
|
||||||
->addByline(pht('Creator: %s', $creator_handle->renderLink()))
|
->addByline(pht('Creator: %s', $creator_handle->renderLink()))
|
||||||
->addAttribute(pht('From %s to %s', $from, $to))
|
->addAttribute(pht('From %s to %s', $from, $to))
|
||||||
->addAttribute(id(new PhutilUTF8StringTruncator())
|
->addAttribute(id(new PhutilUTF8StringTruncator())
|
||||||
|
@ -371,7 +373,8 @@ final class PhabricatorCalendarEventSearchEngine
|
||||||
$event->setUserPHID($status->getUserPHID());
|
$event->setUserPHID($status->getUserPHID());
|
||||||
$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->setEventID($status->getID());
|
$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);
|
||||||
}
|
}
|
||||||
|
@ -423,7 +426,7 @@ final class PhabricatorCalendarEventSearchEngine
|
||||||
$event->setViewerIsInvited($viewer_is_invited);
|
$event->setViewerIsInvited($viewer_is_invited);
|
||||||
|
|
||||||
$event->setName($status->getName());
|
$event->setName($status->getName());
|
||||||
$event->setURI('/'.$status->getMonogram());
|
$event->setURI($status->getURI());
|
||||||
$day_view->addEvent($event);
|
$day_view->addEvent($event);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -20,6 +20,14 @@ final class PhabricatorCalendarEvent extends PhabricatorCalendarDAO
|
||||||
protected $icon;
|
protected $icon;
|
||||||
protected $mailKey;
|
protected $mailKey;
|
||||||
|
|
||||||
|
protected $isRecurring = 0;
|
||||||
|
protected $recurrenceFrequency = array();
|
||||||
|
protected $recurrenceEndDate;
|
||||||
|
|
||||||
|
private $isGhostEvent = false;
|
||||||
|
protected $instanceOfEventPHID;
|
||||||
|
protected $sequenceIndex;
|
||||||
|
|
||||||
protected $viewPolicy;
|
protected $viewPolicy;
|
||||||
protected $editPolicy;
|
protected $editPolicy;
|
||||||
|
|
||||||
|
@ -36,8 +44,13 @@ final class PhabricatorCalendarEvent extends PhabricatorCalendarDAO
|
||||||
->withClasses(array('PhabricatorCalendarApplication'))
|
->withClasses(array('PhabricatorCalendarApplication'))
|
||||||
->executeOne();
|
->executeOne();
|
||||||
|
|
||||||
|
$view_policy = null;
|
||||||
|
$is_recurring = 0;
|
||||||
|
|
||||||
if ($mode == 'public') {
|
if ($mode == 'public') {
|
||||||
$view_policy = PhabricatorPolicies::getMostOpenPolicy();
|
$view_policy = PhabricatorPolicies::getMostOpenPolicy();
|
||||||
|
} else if ($mode == 'recurring') {
|
||||||
|
$is_recurring = true;
|
||||||
} else {
|
} else {
|
||||||
$view_policy = $actor->getPHID();
|
$view_policy = $actor->getPHID();
|
||||||
}
|
}
|
||||||
|
@ -46,6 +59,7 @@ final class PhabricatorCalendarEvent extends PhabricatorCalendarDAO
|
||||||
->setUserPHID($actor->getPHID())
|
->setUserPHID($actor->getPHID())
|
||||||
->setIsCancelled(0)
|
->setIsCancelled(0)
|
||||||
->setIsAllDay(0)
|
->setIsAllDay(0)
|
||||||
|
->setIsRecurring($is_recurring)
|
||||||
->setIcon(self::DEFAULT_ICON)
|
->setIcon(self::DEFAULT_ICON)
|
||||||
->setViewPolicy($view_policy)
|
->setViewPolicy($view_policy)
|
||||||
->setEditPolicy($actor->getPHID())
|
->setEditPolicy($actor->getPHID())
|
||||||
|
@ -180,12 +194,19 @@ final class PhabricatorCalendarEvent extends PhabricatorCalendarDAO
|
||||||
'isAllDay' => 'bool',
|
'isAllDay' => 'bool',
|
||||||
'icon' => 'text32',
|
'icon' => 'text32',
|
||||||
'mailKey' => 'bytes20',
|
'mailKey' => 'bytes20',
|
||||||
|
'isRecurring' => 'bool',
|
||||||
|
'recurrenceEndDate' => 'epoch?',
|
||||||
|
'instanceOfEventPHID' => 'phid?',
|
||||||
|
'sequenceIndex' => 'uint32?',
|
||||||
),
|
),
|
||||||
self::CONFIG_KEY_SCHEMA => array(
|
self::CONFIG_KEY_SCHEMA => array(
|
||||||
'userPHID_dateFrom' => array(
|
'userPHID_dateFrom' => array(
|
||||||
'columns' => array('userPHID', 'dateTo'),
|
'columns' => array('userPHID', 'dateTo'),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
self::CONFIG_SERIALIZATION => array(
|
||||||
|
'recurrenceFrequency' => self::SERIALIZATION_JSON,
|
||||||
|
),
|
||||||
) + parent::getConfiguration();
|
) + parent::getConfiguration();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -238,6 +259,69 @@ final class PhabricatorCalendarEvent extends PhabricatorCalendarDAO
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function getIsGhostEvent() {
|
||||||
|
return $this->isGhostEvent;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function setIsGhostEvent($is_ghost_event) {
|
||||||
|
$this->isGhostEvent = $is_ghost_event;
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function generateNthGhost(
|
||||||
|
$sequence_index,
|
||||||
|
PhabricatorUser $actor) {
|
||||||
|
|
||||||
|
$frequency = $this->getFrequencyUnit();
|
||||||
|
$modify_key = '+'.$sequence_index.' '.$frequency;
|
||||||
|
|
||||||
|
$date = $this->dateFrom;
|
||||||
|
$date_time = PhabricatorTime::getDateTimeFromEpoch($date, $actor);
|
||||||
|
$date_time->modify($modify_key);
|
||||||
|
$date = $date_time->format('U');
|
||||||
|
|
||||||
|
$duration = $this->dateTo - $this->dateFrom;
|
||||||
|
|
||||||
|
$edit_policy = PhabricatorPolicies::POLICY_NOONE;
|
||||||
|
|
||||||
|
$ghost_event = id(clone $this)
|
||||||
|
->setIsGhostEvent(true)
|
||||||
|
->setDateFrom($date)
|
||||||
|
->setDateTo($date + $duration)
|
||||||
|
->setIsRecurring(false)
|
||||||
|
->setRecurrenceFrequency(null)
|
||||||
|
->setInstanceOfEventPHID($this->getPHID())
|
||||||
|
->setSequenceIndex($sequence_index)
|
||||||
|
->setEditPolicy($edit_policy);
|
||||||
|
|
||||||
|
return $ghost_event;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getFrequencyUnit() {
|
||||||
|
$frequency = idx($this->recurrenceFrequency, 'rule');
|
||||||
|
|
||||||
|
switch ($frequency) {
|
||||||
|
case 'daily':
|
||||||
|
return 'day';
|
||||||
|
case 'weekly':
|
||||||
|
return 'week';
|
||||||
|
case 'monthly':
|
||||||
|
return 'month';
|
||||||
|
case 'yearly':
|
||||||
|
return 'yearly';
|
||||||
|
default:
|
||||||
|
return 'day';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getURI() {
|
||||||
|
$uri = '/'.$this->getMonogram();
|
||||||
|
if ($this->isGhostEvent) {
|
||||||
|
$uri = $uri.'/'.$this->sequenceIndex;
|
||||||
|
}
|
||||||
|
return $uri;
|
||||||
|
}
|
||||||
|
|
||||||
/* -( Markup Interface )--------------------------------------------------- */
|
/* -( Markup Interface )--------------------------------------------------- */
|
||||||
|
|
||||||
|
|
||||||
|
@ -307,6 +391,9 @@ final class PhabricatorCalendarEvent extends PhabricatorCalendarDAO
|
||||||
public function hasAutomaticCapability($capability, PhabricatorUser $viewer) {
|
public function hasAutomaticCapability($capability, PhabricatorUser $viewer) {
|
||||||
// The owner of a task can always view and edit it.
|
// The owner of a task can always view and edit it.
|
||||||
$user_phid = $this->getUserPHID();
|
$user_phid = $this->getUserPHID();
|
||||||
|
if ($this->isGhostEvent) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
if ($user_phid) {
|
if ($user_phid) {
|
||||||
$viewer_phid = $viewer->getPHID();
|
$viewer_phid = $viewer->getPHID();
|
||||||
if ($viewer_phid == $user_phid) {
|
if ($viewer_phid == $user_phid) {
|
||||||
|
@ -328,7 +415,8 @@ final class PhabricatorCalendarEvent extends PhabricatorCalendarDAO
|
||||||
|
|
||||||
public function describeAutomaticCapability($capability) {
|
public function describeAutomaticCapability($capability) {
|
||||||
return pht('The owner of an event can always view and edit it,
|
return pht('The owner of an event can always view and edit it,
|
||||||
and invitees can always view it.');
|
and invitees can always view it, except if the event is an
|
||||||
|
instance of a recurring event.');
|
||||||
}
|
}
|
||||||
|
|
||||||
/* -( PhabricatorApplicationTransactionInterface )------------------------- */
|
/* -( PhabricatorApplicationTransactionInterface )------------------------- */
|
||||||
|
|
|
@ -12,6 +12,13 @@ final class PhabricatorCalendarEventTransaction
|
||||||
const TYPE_ICON = 'calendar.icon';
|
const TYPE_ICON = 'calendar.icon';
|
||||||
const TYPE_INVITE = 'calendar.invite';
|
const TYPE_INVITE = 'calendar.invite';
|
||||||
|
|
||||||
|
const TYPE_RECURRING = 'calendar.recurring';
|
||||||
|
const TYPE_FREQUENCY = 'calendar.frequency';
|
||||||
|
const TYPE_RECURRENCE_END_DATE = 'calendar.recurrenceenddate';
|
||||||
|
|
||||||
|
const TYPE_INSTANCE_OF_EVENT = 'calendar.instanceofevent';
|
||||||
|
const TYPE_SEQUENCE_INDEX = 'calendar.sequenceindex';
|
||||||
|
|
||||||
const MAILTAG_RESCHEDULE = 'calendar-reschedule';
|
const MAILTAG_RESCHEDULE = 'calendar-reschedule';
|
||||||
const MAILTAG_CONTENT = 'calendar-content';
|
const MAILTAG_CONTENT = 'calendar-content';
|
||||||
const MAILTAG_OTHER = 'calendar-other';
|
const MAILTAG_OTHER = 'calendar-other';
|
||||||
|
@ -38,6 +45,11 @@ final class PhabricatorCalendarEventTransaction
|
||||||
case self::TYPE_DESCRIPTION:
|
case self::TYPE_DESCRIPTION:
|
||||||
case self::TYPE_CANCEL:
|
case self::TYPE_CANCEL:
|
||||||
case self::TYPE_ALL_DAY:
|
case self::TYPE_ALL_DAY:
|
||||||
|
case self::TYPE_RECURRING:
|
||||||
|
case self::TYPE_FREQUENCY:
|
||||||
|
case self::TYPE_RECURRENCE_END_DATE:
|
||||||
|
case self::TYPE_INSTANCE_OF_EVENT:
|
||||||
|
case self::TYPE_SEQUENCE_INDEX:
|
||||||
$phids[] = $this->getObjectPHID();
|
$phids[] = $this->getObjectPHID();
|
||||||
break;
|
break;
|
||||||
case self::TYPE_INVITE:
|
case self::TYPE_INVITE:
|
||||||
|
@ -60,6 +72,11 @@ final class PhabricatorCalendarEventTransaction
|
||||||
case self::TYPE_CANCEL:
|
case self::TYPE_CANCEL:
|
||||||
case self::TYPE_ALL_DAY:
|
case self::TYPE_ALL_DAY:
|
||||||
case self::TYPE_INVITE:
|
case self::TYPE_INVITE:
|
||||||
|
case self::TYPE_RECURRING:
|
||||||
|
case self::TYPE_FREQUENCY:
|
||||||
|
case self::TYPE_RECURRENCE_END_DATE:
|
||||||
|
case self::TYPE_INSTANCE_OF_EVENT:
|
||||||
|
case self::TYPE_SEQUENCE_INDEX:
|
||||||
return ($old === null);
|
return ($old === null);
|
||||||
}
|
}
|
||||||
return parent::shouldHide();
|
return parent::shouldHide();
|
||||||
|
@ -75,6 +92,11 @@ final class PhabricatorCalendarEventTransaction
|
||||||
case self::TYPE_DESCRIPTION:
|
case self::TYPE_DESCRIPTION:
|
||||||
case self::TYPE_ALL_DAY:
|
case self::TYPE_ALL_DAY:
|
||||||
case self::TYPE_CANCEL:
|
case self::TYPE_CANCEL:
|
||||||
|
case self::TYPE_RECURRING:
|
||||||
|
case self::TYPE_FREQUENCY:
|
||||||
|
case self::TYPE_RECURRENCE_END_DATE:
|
||||||
|
case self::TYPE_INSTANCE_OF_EVENT:
|
||||||
|
case self::TYPE_SEQUENCE_INDEX:
|
||||||
return 'fa-pencil';
|
return 'fa-pencil';
|
||||||
break;
|
break;
|
||||||
case self::TYPE_INVITE:
|
case self::TYPE_INVITE:
|
||||||
|
@ -231,6 +253,12 @@ final class PhabricatorCalendarEventTransaction
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return $text;
|
return $text;
|
||||||
|
case self::TYPE_RECURRING:
|
||||||
|
case self::TYPE_FREQUENCY:
|
||||||
|
case self::TYPE_RECURRENCE_END_DATE:
|
||||||
|
case self::TYPE_INSTANCE_OF_EVENT:
|
||||||
|
case self::TYPE_SEQUENCE_INDEX:
|
||||||
|
return pht('Recurring event has been updated');
|
||||||
}
|
}
|
||||||
return parent::getTitle();
|
return parent::getTitle();
|
||||||
}
|
}
|
||||||
|
@ -411,6 +439,12 @@ final class PhabricatorCalendarEventTransaction
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return $text;
|
return $text;
|
||||||
|
case self::TYPE_RECURRING:
|
||||||
|
case self::TYPE_FREQUENCY:
|
||||||
|
case self::TYPE_RECURRENCE_END_DATE:
|
||||||
|
case self::TYPE_INSTANCE_OF_EVENT:
|
||||||
|
case self::TYPE_SEQUENCE_INDEX:
|
||||||
|
return pht('Recurring event has been updated');
|
||||||
}
|
}
|
||||||
|
|
||||||
return parent::getTitleForFeed();
|
return parent::getTitleForFeed();
|
||||||
|
|
|
@ -89,7 +89,7 @@ final class PHUICalendarListView extends AphrontTagView {
|
||||||
$content = javelin_tag(
|
$content = javelin_tag(
|
||||||
'a',
|
'a',
|
||||||
array(
|
array(
|
||||||
'href' => '/E'.$event->getEventID(),
|
'href' => $event->getURI(),
|
||||||
'sigil' => 'has-tooltip',
|
'sigil' => 'has-tooltip',
|
||||||
'meta' => array(
|
'meta' => array(
|
||||||
'tip' => $tip,
|
'tip' => $tip,
|
||||||
|
|
|
@ -140,7 +140,7 @@ textarea::-webkit-input-placeholder {
|
||||||
color: {$lightgreytext};
|
color: {$lightgreytext};
|
||||||
}
|
}
|
||||||
|
|
||||||
select[disabled="disabled"],
|
select[disabled],
|
||||||
input[disabled="disabled"] {
|
input[disabled] {
|
||||||
opacity: 0.5;
|
opacity: 0.5;
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,14 @@
|
||||||
|
/**
|
||||||
|
* @provides javelin-behavior-recurring-edit
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
JX.behavior('recurring-edit', function(config) {
|
||||||
|
var checkbox = JX.$(config.isRecurring);
|
||||||
|
JX.DOM.listen(checkbox, 'change', null, function() {
|
||||||
|
var frequency = JX.$(config.frequency);
|
||||||
|
|
||||||
|
frequency.disabled = checkbox.checked ? false : true;
|
||||||
|
});
|
||||||
|
|
||||||
|
});
|
Loading…
Reference in a new issue