diff --git a/src/applications/calendar/query/PhabricatorCalendarEventSearchEngine.php b/src/applications/calendar/query/PhabricatorCalendarEventSearchEngine.php index 6e79d44940..d84f81cac4 100644 --- a/src/applications/calendar/query/PhabricatorCalendarEventSearchEngine.php +++ b/src/applications/calendar/query/PhabricatorCalendarEventSearchEngine.php @@ -1,462 +1,467 @@ setParameter( 'rangeStart', $this->readDateFromRequest($request, 'rangeStart')); $saved->setParameter( 'rangeEnd', $this->readDateFromRequest($request, 'rangeEnd')); $saved->setParameter( 'upcoming', $this->readBoolFromRequest($request, 'upcoming')); $saved->setParameter( 'invitedPHIDs', $this->readUsersFromRequest($request, 'invited')); $saved->setParameter( 'creatorPHIDs', $this->readUsersFromRequest($request, 'creators')); $saved->setParameter( 'isCancelled', $request->getStr('isCancelled')); $saved->setParameter( 'display', $request->getStr('display')); return $saved; } public function buildQueryFromSavedQuery(PhabricatorSavedQuery $saved) { $query = id(new PhabricatorCalendarEventQuery()); $viewer = $this->requireViewer(); $timezone = new DateTimeZone($viewer->getTimezoneIdentifier()); $min_range = $this->getDateFrom($saved)->getEpoch(); $max_range = $this->getDateTo($saved)->getEpoch(); if ($saved->getParameter('display') == 'month' || $saved->getParameter('display') == 'day') { list($start_year, $start_month, $start_day) = $this->getDisplayYearAndMonthAndDay($saved); $start_day = new DateTime( "{$start_year}-{$start_month}-{$start_day}", $timezone); $next = clone $start_day; if ($saved->getParameter('display') == 'month') { $next->modify('+1 month'); } else if ($saved->getParameter('display') == 'day') { $next->modify('+6 day'); } $display_start = $start_day->format('U'); $display_end = $next->format('U'); if (!$min_range || ($min_range < $display_start)) { $min_range = $display_start; } if (!$max_range || ($max_range > $display_end)) { $max_range = $display_end; } } if ($saved->getParameter('upcoming')) { if ($min_range) { $min_range = max(time(), $min_range); } else { $min_range = time(); } } if ($min_range || $max_range) { $query->withDateRange($min_range, $max_range); } $invited_phids = $saved->getParameter('invitedPHIDs'); if ($invited_phids) { $query->withInvitedPHIDs($invited_phids); } $creator_phids = $saved->getParameter('creatorPHIDs'); if ($creator_phids) { $query->withCreatorPHIDs($creator_phids); } $is_cancelled = $saved->getParameter('isCancelled'); switch ($is_cancelled) { case 'active': $query->withIsCancelled(false); break; case 'cancelled': $query->withIsCancelled(true); break; } return $query; } public function buildSearchForm( AphrontFormView $form, PhabricatorSavedQuery $saved) { $range_start = $this->getDateFrom($saved); $e_start = null; $range_end = $this->getDateTo($saved); $e_end = null; if (!$range_start->isValid()) { $this->addError(pht('Start date is not valid.')); $e_start = pht('Invalid'); } if (!$range_end->isValid()) { $this->addError(pht('End date is not valid.')); $e_end = pht('Invalid'); } $start_epoch = $range_start->getEpoch(); $end_epoch = $range_end->getEpoch(); if ($start_epoch && $end_epoch && ($start_epoch > $end_epoch)) { $this->addError(pht('End date must be after start date.')); $e_start = pht('Invalid'); $e_end = pht('Invalid'); } $upcoming = $saved->getParameter('upcoming'); $is_cancelled = $saved->getParameter('isCancelled', 'active'); $display = $saved->getParameter('display', 'month'); $invited_phids = $saved->getParameter('invitedPHIDs', array()); $creator_phids = $saved->getParameter('creatorPHIDs', array()); $resolution_types = array( 'active' => pht('Active Events Only'), 'cancelled' => pht('Cancelled Events Only'), 'both' => pht('Both Cancelled and Active Events'), ); $display_options = array( 'month' => pht('Month View'), 'day' => pht('Day View (beta)'), 'list' => pht('List View'), ); $form ->appendControl( id(new AphrontFormTokenizerControl()) ->setDatasource(new PhabricatorPeopleDatasource()) ->setName('creators') ->setLabel(pht('Created By')) ->setValue($creator_phids)) ->appendControl( id(new AphrontFormTokenizerControl()) ->setDatasource(new PhabricatorPeopleDatasource()) ->setName('invited') ->setLabel(pht('Invited')) ->setValue($invited_phids)) ->appendChild( id(new AphrontFormDateControl()) ->setLabel(pht('Occurs After')) ->setUser($this->requireViewer()) ->setName('rangeStart') ->setError($e_start) ->setValue($range_start)) ->appendChild( id(new AphrontFormDateControl()) ->setLabel(pht('Occurs Before')) ->setUser($this->requireViewer()) ->setName('rangeEnd') ->setError($e_end) ->setValue($range_end)) ->appendChild( id(new AphrontFormCheckboxControl()) ->addCheckbox( 'upcoming', 1, pht('Show only upcoming events.'), $upcoming)) ->appendChild( id(new AphrontFormSelectControl()) ->setLabel(pht('Cancelled Events')) ->setName('isCancelled') ->setValue($is_cancelled) ->setOptions($resolution_types)) ->appendChild( id(new AphrontFormSelectControl()) ->setLabel(pht('Display Options')) ->setName('display') ->setValue($display) ->setOptions($display_options)); } protected function getURI($path) { return '/calendar/'.$path; } protected function getBuiltinQueryNames() { $names = array( 'month' => pht('Month View'), 'day' => pht('Day View'), 'upcoming' => pht('Upcoming Events'), 'all' => pht('All Events'), ); return $names; } public function setCalendarYearAndMonthAndDay($year, $month, $day = null) { $this->calendarYear = $year; $this->calendarMonth = $month; $this->calendarDay = $day; return $this; } public function buildSavedQueryFromBuiltin($query_key) { $query = $this->newSavedQuery(); $query->setQueryKey($query_key); switch ($query_key) { case 'month': return $query->setParameter('display', 'month'); case 'day': return $query->setParameter('display', 'day'); case 'upcoming': return $query->setParameter('upcoming', true); case 'all': return $query; } return parent::buildSavedQueryFromBuiltin($query_key); } protected function getRequiredHandlePHIDsForResultList( array $objects, PhabricatorSavedQuery $query) { $phids = array(); foreach ($objects as $event) { $phids[$event->getUserPHID()] = 1; } return array_keys($phids); } protected function renderResultList( array $events, PhabricatorSavedQuery $query, array $handles) { if ($query->getParameter('display') == 'month') { return $this->buildCalendarView($events, $query, $handles); } else if ($query->getParameter('display') == 'day') { return $this->buildCalendarDayView($events, $query, $handles); } assert_instances_of($events, 'PhabricatorCalendarEvent'); $viewer = $this->requireViewer(); $list = new PHUIObjectItemListView(); foreach ($events as $event) { $href = '/E'.$event->getID(); $from = phabricator_datetime($event->getDateFrom(), $viewer); $to = phabricator_datetime($event->getDateTo(), $viewer); $creator_handle = $handles[$event->getUserPHID()]; $name = (strlen($event->getName())) ? $event->getName() : $event->getTerseSummary($viewer); $color = ($event->getStatus() == PhabricatorCalendarEvent::STATUS_AWAY) ? 'red' : 'yellow'; $item = id(new PHUIObjectItemView()) ->setHeader($name) ->setHref($href) ->setBarColor($color) ->addByline(pht('Creator: %s', $creator_handle->renderLink())) ->addAttribute(pht('From %s to %s', $from, $to)) ->addAttribute(id(new PhutilUTF8StringTruncator()) ->setMaximumGlyphs(64) ->truncateString($event->getDescription())); $list->addItem($item); } return $list; } private function buildCalendarView( array $statuses, PhabricatorSavedQuery $query, array $handles) { $viewer = $this->requireViewer(); $now = time(); list($start_year, $start_month) = $this->getDisplayYearAndMonthAndDay($query); $now_year = phabricator_format_local_time($now, $viewer, 'Y'); $now_month = phabricator_format_local_time($now, $viewer, 'm'); $now_day = phabricator_format_local_time($now, $viewer, 'j'); if ($start_month == $now_month && $start_year == $now_year) { $month_view = new PHUICalendarMonthView( $start_month, $start_year, $now_day); } else { $month_view = new PHUICalendarMonthView( $start_month, $start_year); } $month_view->setUser($viewer); $phids = mpull($statuses, 'getUserPHID'); /* Assign Colors */ $unique = array_unique($phids); $allblue = false; $calcolors = CalendarColors::getColors(); if (count($unique) > count($calcolors)) { $allblue = true; } $i = 0; $eventcolor = array(); foreach ($unique as $phid) { if ($allblue) { $eventcolor[$phid] = CalendarColors::COLOR_SKY; } else { $eventcolor[$phid] = $calcolors[$i]; } $i++; } foreach ($statuses as $status) { $event = new AphrontCalendarEventView(); $event->setEpochRange($status->getDateFrom(), $status->getDateTo()); $name_text = $handles[$status->getUserPHID()]->getName(); $status_text = $status->getHumanStatus(); $event->setUserPHID($status->getUserPHID()); $event->setDescription(pht('%s (%s)', $name_text, $status_text)); $event->setName($status_text); $event->setEventID($status->getID()); $event->setColor($eventcolor[$status->getUserPHID()]); $month_view->addEvent($event); } $month_view->setBrowseURI( $this->getURI('query/'.$query->getQueryKey().'/')); return $month_view; } private function buildCalendarDayView( array $statuses, PhabricatorSavedQuery $query, array $handles) { $viewer = $this->requireViewer(); list($start_year, $start_month, $start_day) = $this->getDisplayYearAndMonthAndDay($query); $day_view = new PHUICalendarDayView( $start_year, $start_month, $start_day); $day_view->setUser($viewer); $phids = mpull($statuses, 'getUserPHID'); foreach ($statuses as $status) { + if ($status->getIsCancelled()) { + continue; + } + $event = new AphrontCalendarEventView(); $event->setEventID($status->getID()); $event->setEpochRange($status->getDateFrom(), $status->getDateTo()); + $event->setIsAllDay($status->getIsAllDay()); $event->setName($status->getName()); $event->setURI('/'.$status->getMonogram()); $day_view->addEvent($event); } $day_view->setBrowseURI( $this->getURI('query/'.$query->getQueryKey().'/')); return $day_view; } private function getDisplayYearAndMonthAndDay( PhabricatorSavedQuery $query) { $viewer = $this->requireViewer(); if ($this->calendarYear && $this->calendarMonth) { $start_year = $this->calendarYear; $start_month = $this->calendarMonth; $start_day = $this->calendarDay ? $this->calendarDay : 1; } else { $epoch = $this->getDateFrom($query)->getEpoch(); if (!$epoch) { $epoch = $this->getDateTo($query)->getEpoch(); if (!$epoch) { $epoch = time(); } } $start_year = phabricator_format_local_time($epoch, $viewer, 'Y'); $start_month = phabricator_format_local_time($epoch, $viewer, 'm'); $start_day = phabricator_format_local_time($epoch, $viewer, 'd'); } return array($start_year, $start_month, $start_day); } public function getPageSize(PhabricatorSavedQuery $saved) { return $saved->getParameter('limit', 1000); } private function getDateFrom(PhabricatorSavedQuery $saved) { return $this->getDate($saved, 'rangeStart'); } private function getDateTo(PhabricatorSavedQuery $saved) { return $this->getDate($saved, 'rangeEnd'); } private function getDate(PhabricatorSavedQuery $saved, $key) { $viewer = $this->requireViewer(); $wild = $saved->getParameter($key); if ($wild) { $value = AphrontFormDateControlValue::newFromWild($viewer, $wild); } else { $value = AphrontFormDateControlValue::newFromEpoch( $viewer, PhabricatorTime::getTodayMidnightDateTime($viewer)->format('U')); $value->setEnabled(false); } $value->setOptional(true); return $value; } } diff --git a/src/applications/calendar/view/AphrontCalendarEventView.php b/src/applications/calendar/view/AphrontCalendarEventView.php index aebfaa9a50..11dbff3847 100644 --- a/src/applications/calendar/view/AphrontCalendarEventView.php +++ b/src/applications/calendar/view/AphrontCalendarEventView.php @@ -1,104 +1,107 @@ uri = $uri; return $this; } public function getURI() { return $this->uri; } 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 setColor($color) { $this->color = $color; return $this; } public function getColor() { if ($this->color) { return $this->color; } else { return CalendarColors::COLOR_SKY; } } - public function getAllDay() { - $time = (60 * 60 * 22); - if (($this->getEpochEnd() - $this->getEpochStart()) >= $time) { - return true; - } - return false; + public function setIsAllDay($is_all_day) { + $this->isAllDay = $is_all_day; + return $this; } + public function getIsAllDay() { + return $this->isAllDay; + } + + public function getMultiDay() { $nextday = strtotime('12:00 AM Tomorrow', $this->getEpochStart()); if ($this->getEpochEnd() > $nextday) { return true; } return false; } public function render() { throw new Exception('Events are only rendered indirectly.'); } } diff --git a/src/view/phui/calendar/PHUICalendarDayView.php b/src/view/phui/calendar/PHUICalendarDayView.php index 6d42fdcec3..c3f0d6b61d 100644 --- a/src/view/phui/calendar/PHUICalendarDayView.php +++ b/src/view/phui/calendar/PHUICalendarDayView.php @@ -1,411 +1,452 @@ events[] = $event; return $this; } public function setBrowseURI($browse_uri) { $this->browseURI = $browse_uri; return $this; } private function getBrowseURI() { return $this->browseURI; } public function __construct($year, $month, $day = null) { $this->day = $day; $this->month = $month; $this->year = $year; } public function render() { require_celerity_resource('phui-calendar-day-css'); $hours = $this->getHoursOfDay(); $hourly_events = array(); $rows = array(); + $all_day_events = $this->getAllDayEvents(); + // sort events into buckets by their start time // pretend no events overlap foreach ($hours as $hour) { - $events = array(); + $current_hour_events = array(); $hour_start = $hour->format('U'); $hour_end = id(clone $hour)->modify('+1 hour')->format('U'); + + if ($hour == $this->getDateTime()) { + foreach ($all_day_events as $all_day_event) { + $all_day_start = $all_day_event->getEpochStart(); + $all_day_end = $all_day_event->getEpochEnd(); + $day_end = id(clone $hour)->modify('+1 day')->format('U') - 1; + + if ($all_day_start < $day_end && $all_day_end > $hour_start) { + + $current_hour_events[] = $all_day_event; + $this->todayEvents[] = $all_day_event; + } + } + } foreach ($this->events as $event) { + if ($event->getIsAllDay()) { + continue; + } if ($event->getEpochStart() >= $hour_start && $event->getEpochStart() < $hour_end) { - $events[] = $event; + $current_hour_events[] = $event; + $this->todayEvents[] = $event; } } - $count_events = count($events); - $n = 0; - foreach ($events as $event) { + foreach ($current_hour_events as $event) { $event_start = $event->getEpochStart(); $event_end = $event->getEpochEnd(); - $top = ((($event_start - $hour_start) / ($hour_end - $hour_start)) - * 100).'%'; - $height = ((($event_end - $event_start) / ($hour_end - $hour_start)) - * 100).'%'; + $top = (($event_start - $hour_start) / ($hour_end - $hour_start)) + * 100; + $top = max(0, $top); + + $height = (($event_end - $event_start) / ($hour_end - $hour_start)) + * 100; + $height = min(2400, $height); $hourly_events[$event->getEventID()] = array( 'hour' => $hour, 'event' => $event, 'offset' => '0', 'width' => '100%', - 'top' => $top, - 'height' => $height, + 'top' => $top.'%', + 'height' => $height.'%', ); - - $n++; } } - $clusters = $this->findClusters(); + $clusters = $this->findTodayClusters(); foreach ($clusters as $cluster) { $hourly_events = $this->updateEventsFromCluster( $cluster, $hourly_events); } // actually construct table foreach ($hours as $hour) { $drawn_hourly_events = array(); $cell_time = phutil_tag( 'td', array('class' => 'phui-calendar-day-hour'), $hour->format('g A')); foreach ($hourly_events as $hourly_event) { if ($hourly_event['hour'] == $hour) { $drawn_hourly_events[] = $this->drawEvent( $hourly_event['event'], $hourly_event['offset'], $hourly_event['width'], $hourly_event['top'], $hourly_event['height']); } } $cell_event = phutil_tag( 'td', array('class' => 'phui-calendar-day-events'), $drawn_hourly_events); $row = phutil_tag( 'tr', array(), array($cell_time, $cell_event)); $rows[] = $row; } $table = phutil_tag( 'table', array('class' => 'phui-calendar-day-view'), array( '', $rows, )); $header = $this->renderDayViewHeader(); $sidebar = $this->renderSidebar(); $table_box = id(new PHUIObjectBoxView()) ->setHeader($header) ->appendChild($table) ->setFlush(true); $layout = id(new AphrontMultiColumnView()) ->addColumn($sidebar, 'third') ->addColumn($table_box, 'thirds') ->setFluidLayout(true) ->setGutter(AphrontMultiColumnView::GUTTER_MEDIUM); return phutil_tag( 'div', array( 'class' => 'ml', ), $layout); } + private function getAllDayEvents() { + $all_day_events = array(); + + foreach ($this->events as $event) { + if ($event->getIsAllDay()) { + $all_day_events[] = $event; + } + } + + $all_day_events = array_values(msort($all_day_events, 'getEpochStart')); + + return $all_day_events; + } + private function renderSidebar() { $this->events = msort($this->events, 'getEpochStart'); $week_of_boxes = $this->getWeekOfBoxes(); $filled_boxes = array(); - foreach ($week_of_boxes as $weekly_box) { - $start = $weekly_box['start']; - $end = id(clone $start)->modify('+1 day'); + foreach ($week_of_boxes as $day_box) { + $box_start = $day_box['start']; + $box_end = id(clone $box_start)->modify('+1 day'); + + $box_start = $box_start->format('U'); + $box_end = $box_end->format('U'); $box_events = array(); foreach ($this->events as $event) { - if ($event->getEpochStart() >= $start->format('U') && - $event->getEpochStart() < $end->format('U')) { + $event_start = $event->getEpochStart(); + $event_end = $event->getEpochEnd(); + + if ($event_start < $box_end && $event_end > $box_start) { $box_events[] = $event; } } + $filled_boxes[] = $this->renderSidebarBox( $box_events, - $weekly_box['title']); + $day_box['title']); } return $filled_boxes; } private function renderSidebarBox($events, $title) { $widget = new PHUICalendarWidgetView(); $list = id(new PHUICalendarListView()) ->setUser($this->user); if (count($events) == 0) { $list->showBlankState(true); } else { foreach ($events as $event) { $list->addEvent($event); } } $widget ->setCalendarList($list) ->setHeader($title); return $widget; } private function getWeekOfBoxes() { $sidebar_day_boxes = array(); $display_start_day = $this->getDateTime(); $display_end_day = id(clone $display_start_day)->modify('+6 day'); $box_start_time = clone $display_start_day; $today_time = PhabricatorTime::getTodayMidnightDateTime($this->user); $tomorrow_time = clone $today_time; $tomorrow_time->modify('+1 day'); while ($box_start_time <= $display_end_day) { if ($box_start_time == $today_time) { $title = pht('Today'); } else if ($box_start_time == $tomorrow_time) { $title = pht('Tomorrow'); } else { $title = $box_start_time->format('l'); } $sidebar_day_boxes[] = array( 'title' => $title, 'start' => clone $box_start_time, ); $box_start_time->modify('+1 day'); } return $sidebar_day_boxes; } private function renderDayViewHeader() { $button_bar = null; // check for a browseURI, which means we need "fancy" prev / next UI $uri = $this->getBrowseURI(); if ($uri) { list($prev_year, $prev_month, $prev_day) = $this->getPrevDay(); $prev_uri = $uri.$prev_year.'/'.$prev_month.'/'.$prev_day.'/'; list($next_year, $next_month, $next_day) = $this->getNextDay(); $next_uri = $uri.$next_year.'/'.$next_month.'/'.$next_day.'/'; $button_bar = new PHUIButtonBarView(); $left_icon = id(new PHUIIconView()) ->setIconFont('fa-chevron-left bluegrey'); $left = id(new PHUIButtonView()) ->setTag('a') ->setColor(PHUIButtonView::GREY) ->setHref($prev_uri) ->setTitle(pht('Previous Day')) ->setIcon($left_icon); $right_icon = id(new PHUIIconView()) ->setIconFont('fa-chevron-right bluegrey'); $right = id(new PHUIButtonView()) ->setTag('a') ->setColor(PHUIButtonView::GREY) ->setHref($next_uri) ->setTitle(pht('Next Day')) ->setIcon($right_icon); $button_bar->addButton($left); $button_bar->addButton($right); } $day_of_week = $this->getDayOfWeek(); $header_text = $this->getDateTime()->format('F j, Y'); $header_text = $day_of_week.', '.$header_text; $header = id(new PHUIHeaderView()) ->setHeader($header_text); if ($button_bar) { $header->setButtonBar($button_bar); } return $header; } private function updateEventsFromCluster($cluster, $hourly_events) { $cluster_size = count($cluster); - $n = 0; foreach ($cluster as $cluster_member) { $event_id = $cluster_member->getEventID(); $offset = (($n / $cluster_size) * 100).'%'; $width = ((1 / $cluster_size) * 100).'%'; if (isset($hourly_events[$event_id])) { $hourly_events[$event_id]['offset'] = $offset; $hourly_events[$event_id]['width'] = $width; } $n++; } return $hourly_events; } private function drawEvent( AphrontCalendarEventView $event, $offset, $width, $top, $height) { $name = phutil_tag( 'a', array( 'class' => 'phui-calendar-day-event-link', 'href' => $event->getURI(), ), $event->getName()); $div = phutil_tag( 'div', array( 'class' => 'phui-calendar-day-event', 'style' => 'left: '.$offset .'; width: '.$width .'; top: '.$top .'; height: '.$height .';', ), $name); return $div; } private function getDayOfWeek() { $date = $this->getDateTime(); $day_of_week = $date->format('l'); return $day_of_week; } // returns DateTime of each hour in the day private function getHoursOfDay() { $included_datetimes = array(); $day_datetime = $this->getDateTime(); $day_epoch = $day_datetime->format('U'); $day_datetime->modify('+1 day'); $next_day_epoch = $day_datetime->format('U'); $included_time = $day_epoch; $included_datetime = $this->getDateTime(); while ($included_time < $next_day_epoch) { $included_datetimes[] = clone $included_datetime; $included_datetime->modify('+1 hour'); $included_time = $included_datetime->format('U'); } return $included_datetimes; } private function getPrevDay() { $prev = $this->getDateTime(); $prev->modify('-1 day'); return array( $prev->format('Y'), $prev->format('m'), $prev->format('d'), ); } private function getNextDay() { $next = $this->getDateTime(); $next->modify('+1 day'); return array( $next->format('Y'), $next->format('m'), $next->format('d'), ); } private function getDateTime() { $user = $this->user; $timezone = new DateTimeZone($user->getTimezoneIdentifier()); $day = $this->day; $month = $this->month; $year = $this->year; $date = new DateTime("{$year}-{$month}-{$day} ", $timezone); return $date; } - private function findClusters() { - $events = msort($this->events, 'getEpochStart'); + private function findTodayClusters() { + $events = msort($this->todayEvents, 'getEpochStart'); $clusters = array(); foreach ($events as $event) { $destination_cluster_key = null; $event_start = $event->getEpochStart(); $event_end = $event->getEpochEnd(); foreach ($clusters as $key => $cluster) { foreach ($cluster as $clustered_event) { $compare_event_start = $clustered_event->getEpochStart(); $compare_event_end = $clustered_event->getEpochEnd(); if ($event_start < $compare_event_end && $event_end > $compare_event_start) { $destination_cluster_key = $key; break; } } } if ($destination_cluster_key !== null) { $clusters[$destination_cluster_key][] = $event; } else { $next_cluster = array(); $next_cluster[] = $event; $clusters[] = $next_cluster; } } return $clusters; } } diff --git a/src/view/phui/calendar/PHUICalendarListView.php b/src/view/phui/calendar/PHUICalendarListView.php index fd6a7a0e73..88c78cda9f 100644 --- a/src/view/phui/calendar/PHUICalendarListView.php +++ b/src/view/phui/calendar/PHUICalendarListView.php @@ -1,130 +1,130 @@ events[] = $event; return $this; } public function showBlankState($state) { $this->blankState = $state; return $this; } protected function getTagName() { return 'div'; } protected function getTagAttributes() { require_celerity_resource('phui-calendar-css'); require_celerity_resource('phui-calendar-list-css'); return array('class' => 'phui-calendar-day-list'); } protected function getTagContent() { if (!$this->blankState && empty($this->events)) { return ''; } $events = msort($this->events, 'getEpochStart'); $singletons = array(); $allday = false; foreach ($events as $event) { $color = $event->getColor(); - if ($event->getAllDay()) { + if ($event->getIsAllDay()) { $timelabel = pht('All Day'); } else { $timelabel = phabricator_time( $event->getEpochStart(), $this->getUser()); } $dot = phutil_tag( 'span', array( 'class' => 'phui-calendar-list-dot', ), ''); $title = phutil_tag( 'span', array( 'class' => 'phui-calendar-list-title', ), $this->renderEventLink($event, $allday)); $time = phutil_tag( 'span', array( 'class' => 'phui-calendar-list-time', ), $timelabel); $singletons[] = phutil_tag( 'li', array( 'class' => 'phui-calendar-list-item phui-calendar-'.$color, ), array( $dot, $title, $time, )); } if (empty($singletons)) { $singletons[] = phutil_tag( 'li', array( 'class' => 'phui-calendar-list-item-empty', ), pht('Clear sailing ahead.')); } $list = phutil_tag( 'ul', array( 'class' => 'phui-calendar-list', ), $singletons); return $list; } private function renderEventLink($event) { Javelin::initBehavior('phabricator-tooltips'); if ($event->getMultiDay()) { $tip = pht('%s, Until: %s', $event->getName(), phabricator_date($event->getEpochEnd(), $this->getUser())); } else { $tip = pht('%s, Until: %s', $event->getName(), phabricator_time($event->getEpochEnd(), $this->getUser())); } $description = $event->getDescription(); if (strlen($description) == 0) { $description = pht('(%s)', $event->getName()); } $anchor = javelin_tag( 'a', array( 'sigil' => 'has-tooltip', 'class' => 'phui-calendar-item-link', 'href' => '/E'.$event->getEventID(), 'meta' => array( 'tip' => $tip, 'size' => 200, ), ), $event->getName()); return $anchor; } }