Page MenuHomestyx hydra

No OneTemporary

diff --git a/src/applications/calendar/controller/PhabricatorCalendarBrowseController.php b/src/applications/calendar/controller/PhabricatorCalendarBrowseController.php
index 017f9fe2c4..2ab4ec942f 100644
--- a/src/applications/calendar/controller/PhabricatorCalendarBrowseController.php
+++ b/src/applications/calendar/controller/PhabricatorCalendarBrowseController.php
@@ -1,91 +1,92 @@
<?php
final class PhabricatorCalendarBrowseController
extends PhabricatorCalendarController {
public function processRequest() {
$now = time();
$request = $this->getRequest();
$user = $request->getUser();
$year_d = phabricator_format_local_time($now, $user, 'Y');
$year = $request->getInt('year', $year_d);
$month_d = phabricator_format_local_time($now, $user, 'm');
$month = $request->getInt('month', $month_d);
$holidays = id(new PhabricatorCalendarHoliday())->loadAllWhere(
'day BETWEEN %s AND %s',
"{$year}-{$month}-01",
"{$year}-{$month}-31");
$statuses = id(new PhabricatorUserStatus())
->loadAllWhere(
'dateTo >= %d AND dateFrom <= %d',
strtotime("{$year}-{$month}-01"),
strtotime("{$year}-{$month}-01 next month"));
$month_view = new AphrontCalendarMonthView($month, $year);
$month_view->setBrowseURI($request->getRequestURI());
$month_view->setUser($user);
$month_view->setHolidays($holidays);
$phids = mpull($statuses, 'getUserPHID');
$handles = $this->loadViewerHandles($phids);
foreach ($statuses as $status) {
$event = new AphrontCalendarEventView();
$event->setEpochRange($status->getDateFrom(), $status->getDateTo());
$name_text = $handles[$status->getUserPHID()]->getName();
$status_text = $status->getTextStatus();
$event->setUserPHID($status->getUserPHID());
$event->setName("{$name_text} ({$status_text})");
$details = '';
if ($status->getDescription()) {
$details = "\n\n".rtrim(phutil_escape_html($status->getDescription()));
}
$event->setDescription(
$status->getTerseSummary($user).$details
);
+ $event->setEventID($status->getID());
$month_view->addEvent($event);
}
$nav = $this->buildSideNavView();
$nav->selectFilter('edit');
$nav->appendChild(
array(
$this->getNoticeView(),
'<div style="padding: 2em;">',
$month_view,
'</div>',
));
return $this->buildApplicationPage(
$nav,
array(
'title' => 'Calendar',
'device' => true,
));
}
private function getNoticeView() {
$request = $this->getRequest();
$view = null;
if ($request->getExists('created')) {
$view = id(new AphrontErrorView())
->setSeverity(AphrontErrorView::SEVERITY_NOTICE)
->setTitle(pht('Successfully created your status.'));
} else if ($request->getExists('updated')) {
$view = id(new AphrontErrorView())
->setSeverity(AphrontErrorView::SEVERITY_NOTICE)
->setTitle(pht('Successfully updated your status.'));
} else if ($request->getExists('deleted')) {
$view = id(new AphrontErrorView())
->setSeverity(AphrontErrorView::SEVERITY_NOTICE)
->setTitle(pht('Successfully deleted your status.'));
}
return $view;
}
}
diff --git a/src/applications/calendar/controller/PhabricatorCalendarEditStatusController.php b/src/applications/calendar/controller/PhabricatorCalendarEditStatusController.php
index 5acdd260fb..75afcb3d41 100644
--- a/src/applications/calendar/controller/PhabricatorCalendarEditStatusController.php
+++ b/src/applications/calendar/controller/PhabricatorCalendarEditStatusController.php
@@ -1,152 +1,153 @@
<?php
final class PhabricatorCalendarEditStatusController
extends PhabricatorCalendarController {
private $id;
public function willProcessRequest(array $data) {
$this->id = idx($data, 'id');
}
public function isCreate() {
return !$this->id;
}
public function processRequest() {
$request = $this->getRequest();
$user = $request->getUser();
$start_time = id(new AphrontFormDateControl())
->setUser($user)
->setName('start')
->setLabel(pht('Start'))
->setInitialTime(AphrontFormDateControl::TIME_START_OF_DAY);
$end_time = id(new AphrontFormDateControl())
->setUser($user)
->setName('end')
->setLabel(pht('End'))
->setInitialTime(AphrontFormDateControl::TIME_END_OF_DAY);
if ($this->isCreate()) {
$status = new PhabricatorUserStatus();
$end_value = $end_time->readValueFromRequest($request);
$start_value = $start_time->readValueFromRequest($request);
$submit_label = pht('Create');
$filter = 'status/create/';
$page_title = pht('Create Status');
$redirect = 'created';
} else {
$status = id(new PhabricatorUserStatus())
->loadOneWhere('id = %d', $this->id);
$end_time->setValue($status->getDateTo());
$start_time->setValue($status->getDateFrom());
$submit_label = pht('Update');
$filter = 'status/edit/'.$status->getID().'/';
$page_title = pht('Update Status');
$redirect = 'updated';
if ($status->getUserPHID() != $user->getPHID()) {
return new Aphront403Response();
}
}
$errors = array();
if ($request->isFormPost()) {
$type = $request->getInt('status');
$start_value = $start_time->readValueFromRequest($request);
$end_value = $end_time->readValueFromRequest($request);
$description = $request->getStr('description');
try {
$status
->setUserPHID($user->getPHID())
->setStatus($type)
->setDateFrom($start_value)
->setDateTo($end_value)
->setDescription($description)
->save();
} catch (PhabricatorUserStatusInvalidEpochException $e) {
$errors[] = 'Start must be before end.';
} catch (PhabricatorUserStatusOverlapException $e) {
$errors[] = 'There is already a status within the specified '.
'timeframe. Edit or delete this existing status.';
}
if (!$errors) {
$uri = new PhutilURI($this->getApplicationURI());
$uri->setQueryParams(
array(
'month' => phabricator_format_local_time($status->getDateFrom(),
$user,
'm'),
'year' => phabricator_format_local_time($status->getDateFrom(),
$user,
'Y'),
$redirect => true,
)
);
return id(new AphrontRedirectResponse())
->setURI($uri);
}
}
$error_view = null;
if ($errors) {
$error_view = id(new AphrontErrorView())
->setTitle('Status can not be set!')
->setErrors($errors);
}
$status_select = id(new AphrontFormSelectControl())
->setLabel(pht('Status'))
->setName('status')
+ ->setValue($status->getStatus())
->setOptions($status->getStatusOptions());
$description = id(new AphrontFormTextAreaControl())
->setLabel(pht('Description'))
->setName('description')
->setValue($status->getDescription());
$form = id(new AphrontFormView())
->setUser($user)
->setFlexible(true)
->appendChild($status_select)
->appendChild($start_time)
->appendChild($end_time)
->appendChild($description);
$submit = id(new AphrontFormSubmitControl())
->setValue($submit_label);
if ($this->isCreate()) {
$submit->addCancelButton($this->getApplicationURI());
} else {
$submit->addCancelButton(
$this->getApplicationURI('status/delete/'.$status->getID().'/'),
'Delete Status'
);
}
$form->appendChild($submit);
$nav = $this->buildSideNavView($status);
$nav->selectFilter($filter);
$nav->appendChild(
array(
id(new PhabricatorHeaderView())->setHeader($page_title),
$error_view,
$form,
)
);
return $this->buildApplicationPage(
$nav,
array(
'title' => $page_title,
'device' => true
)
);
}
}
diff --git a/src/applications/calendar/view/AphrontCalendarEventView.php b/src/applications/calendar/view/AphrontCalendarEventView.php
index 60c7fb0f5c..9fef7d4f1b 100644
--- a/src/applications/calendar/view/AphrontCalendarEventView.php
+++ b/src/applications/calendar/view/AphrontCalendarEventView.php
@@ -1,56 +1,65 @@
<?php
final class AphrontCalendarEventView extends AphrontView {
private $userPHID;
private $name;
private $epochStart;
private $epochEnd;
private $description;
+ private $eventID;
+
+ public function setEventID($event_id) {
+ $this->eventID = $event_id;
+ return $this;
+ }
+ public function getEventID() {
+ return $this->eventID;
+ }
public function setUserPHID($user_phid) {
$this->userPHID = $user_phid;
return $this;
}
public function getUserPHID() {
return $this->userPHID;
}
public function setName($name) {
$this->name = $name;
return $this;
}
public function setEpochRange($start, $end) {
$this->epochStart = $start;
$this->epochEnd = $end;
return $this;
}
public function getEpochStart() {
return $this->epochStart;
}
public function getEpochEnd() {
return $this->epochEnd;
}
public function getName() {
return $this->name;
}
public function setDescription($description) {
$this->description = $description;
return $this;
}
public function getDescription() {
return $this->description;
}
public function render() {
throw new Exception("Events are only rendered indirectly.");
}
}
diff --git a/src/applications/calendar/view/AphrontCalendarMonthView.php b/src/applications/calendar/view/AphrontCalendarMonthView.php
index bf5bfd8e25..429c2257e8 100644
--- a/src/applications/calendar/view/AphrontCalendarMonthView.php
+++ b/src/applications/calendar/view/AphrontCalendarMonthView.php
@@ -1,312 +1,321 @@
<?php
final class AphrontCalendarMonthView extends AphrontView {
private $user;
private $month;
private $year;
private $holidays = array();
private $events = array();
private $browseURI;
public function setBrowseURI($browse_uri) {
$this->browseURI = $browse_uri;
return $this;
}
private function getBrowseURI() {
return $this->browseURI;
}
public function setUser(PhabricatorUser $user) {
$this->user = $user;
return $this;
}
public function addEvent(AphrontCalendarEventView $event) {
$this->events[] = $event;
return $this;
}
public function setHolidays(array $holidays) {
assert_instances_of($holidays, 'PhabricatorCalendarHoliday');
$this->holidays = mpull($holidays, null, 'getDay');
return $this;
}
public function __construct($month, $year) {
$this->month = $month;
$this->year = $year;
}
public function render() {
if (empty($this->user)) {
throw new Exception("Call setUser() before render()!");
}
$events = msort($this->events, 'getEpochStart');
$days = $this->getDatesInMonth();
require_celerity_resource('aphront-calendar-view-css');
$first = reset($days);
$empty = $first->format('w');
$markup = array();
$empty_box =
'<div class="aphront-calendar-day aphront-calendar-empty">'.
'</div>';
for ($ii = 0; $ii < $empty; $ii++) {
$markup[] = $empty_box;
}
$show_events = array();
foreach ($days as $day) {
$day_number = $day->format('j');
$holiday = idx($this->holidays, $day->format('Y-m-d'));
$class = 'aphront-calendar-day';
$weekday = $day->format('w');
if ($holiday || $weekday == 0 || $weekday == 6) {
$class .= ' aphront-calendar-not-work-day';
}
$day->setTime(0, 0, 0);
$epoch_start = $day->format('U');
$day->modify('+1 day');
$epoch_end = $day->format('U');
if ($weekday == 0) {
$show_events = array();
} else {
$show_events = array_fill_keys(
array_keys($show_events),
'<div class="aphront-calendar-event aphront-calendar-event-empty">'.
'&nbsp;'.
'</div>');
}
foreach ($events as $event) {
if ($event->getEpochStart() >= $epoch_end) {
// This list is sorted, so we can stop looking.
break;
}
if ($event->getEpochStart() < $epoch_end &&
$event->getEpochEnd() > $epoch_start) {
$show_events[$event->getUserPHID()] = $this->renderEvent(
$event,
$epoch_start,
$epoch_end);
}
}
$holiday_markup = null;
if ($holiday) {
$name = phutil_escape_html($holiday->getName());
$holiday_markup =
'<div class="aphront-calendar-holiday" title="'.$name.'">'.
$name.
'</div>';
}
$markup[] =
'<div class="'.$class.'">'.
'<div class="aphront-calendar-date-number">'.
$day_number.
'</div>'.
$holiday_markup.
implode("\n", $show_events).
'</div>';
}
$table = array();
$rows = array_chunk($markup, 7);
foreach ($rows as $row) {
$table[] = '<tr>';
while (count($row) < 7) {
$row[] = $empty_box;
}
foreach ($row as $cell) {
$table[] = '<td>'.$cell.'</td>';
}
$table[] = '</tr>';
}
$table =
'<table class="aphront-calendar-view">'.
$this->renderCalendarHeader($first).
'<tr class="aphront-calendar-day-of-week-header">'.
'<th>Sun</th>'.
'<th>Mon</th>'.
'<th>Tue</th>'.
'<th>Wed</th>'.
'<th>Thu</th>'.
'<th>Fri</th>'.
'<th>Sat</th>'.
'</tr>'.
implode("\n", $table).
'</table>';
return $table;
}
private function renderCalendarHeader(DateTime $date) {
$colspan = 7;
$left_th = '';
$right_th = '';
// check for a browseURI, which means we need "fancy" prev / next UI
$uri = $this->getBrowseURI();
if ($uri) {
$colspan = 5;
$uri = new PhutilURI($uri);
list($prev_year, $prev_month) = $this->getPrevYearAndMonth();
$query = array('year' => $prev_year, 'month' => $prev_month);
$prev_link = phutil_render_tag(
'a',
array('href' => (string) $uri->setQueryParams($query)),
'&larr;'
);
list($next_year, $next_month) = $this->getNextYearAndMonth();
$query = array('year' => $next_year, 'month' => $next_month);
$next_link = phutil_render_tag(
'a',
array('href' => (string) $uri->setQueryParams($query)),
'&rarr;'
);
$left_th = '<th>'.$prev_link.'</th>';
$right_th = '<th>'.$next_link.'</th>';
}
return
'<tr class="aphront-calendar-month-year-header">'.
$left_th.
'<th colspan="'.$colspan.'">'.$date->format('F Y').'</th>'.
$right_th.
'</tr>';
}
private function getNextYearAndMonth() {
$month = $this->month;
$year = $this->year;
$next_year = $year;
$next_month = $month + 1;
if ($next_month == 13) {
$next_year = $year + 1;
$next_month = 1;
}
return array($next_year, $next_month);
}
private function getPrevYearAndMonth() {
$month = $this->month;
$year = $this->year;
$prev_year = $year;
$prev_month = $month - 1;
if ($prev_month == 0) {
$prev_year = $year - 1;
$prev_month = 12;
}
return array($prev_year, $prev_month);
}
/**
* Return a DateTime object representing the first moment in each day in the
* month, according to the user's locale.
*
* @return list List of DateTimes, one for each day.
*/
private function getDatesInMonth() {
$user = $this->user;
$timezone = new DateTimeZone($user->getTimezoneIdentifier());
$month = $this->month;
$year = $this->year;
// Get the year and month numbers of the following month, so we can
// determine when this month ends.
list($next_year, $next_month) = $this->getNextYearAndMonth();
$end_date = new DateTime("{$next_year}-{$next_month}-01", $timezone);
$end_epoch = $end_date->format('U');
$days = array();
for ($day = 1; $day <= 31; $day++) {
$day_date = new DateTime("{$year}-{$month}-{$day}", $timezone);
$day_epoch = $day_date->format('U');
if ($day_epoch >= $end_epoch) {
break;
} else {
$days[] = $day_date;
}
}
return $days;
}
private function renderEvent(
AphrontCalendarEventView $event,
$epoch_start,
$epoch_end) {
$user = $this->user;
$event_start = $event->getEpochStart();
$event_end = $event->getEpochEnd();
$classes = array();
$when = array();
$classes[] = 'aphront-calendar-event';
if ($event_start < $epoch_start) {
$classes[] = 'aphront-calendar-event-continues-before';
$when[] = 'Started '.phabricator_datetime($event_start, $user);
} else {
$when[] = 'Starts at '.phabricator_time($event_start, $user);
}
if ($event_end > $epoch_end) {
$classes[] = 'aphront-calendar-event-continues-after';
$when[] = 'Ends '.phabricator_datetime($event_end, $user);
} else {
$when[] = 'Ends at '.phabricator_time($event_end, $user);
}
Javelin::initBehavior('phabricator-tooltips');
$info = $event->getName();
if ($event->getDescription()) {
$info .= "\n\n".$event->getDescription();
}
+ if ($user->getPHID() == $event->getUserPHID()) {
+ $tag = 'a';
+ $href = '/calendar/status/edit/'.$event->getEventID().'/';
+ } else {
+ $tag = 'div';
+ $href = null;
+ }
+
$text_div = javelin_render_tag(
- 'div',
+ $tag,
array(
'sigil' => 'has-tooltip',
'meta' => array(
- 'tip' => $info."\n\n".implode("\n", $when),
- 'size' => 240,
+ 'tip' => $info."\n\n".implode("\n", $when),
+ 'size' => 240,
),
'class' => 'aphront-calendar-event-text',
+ 'href' => $href,
),
phutil_escape_html(phutil_utf8_shorten($event->getName(), 32)));
return javelin_render_tag(
'div',
array(
'class' => implode(' ', $classes),
),
$text_div);
}
}

File Metadata

Mime Type
text/x-diff
Expires
Fri, Oct 31, 11:39 AM (17 h, 8 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
312173
Default Alt Text
(18 KB)

Event Timeline