From 7fd401d0e0234982d89286315f29eaf61b8198af Mon Sep 17 00:00:00 2001
From: lkassianik <lyubakassianik@gmail.com>
Date: Wed, 6 May 2015 18:41:48 -0700
Subject: [PATCH] First stab at Calendar day view sidebar

Summary: Ref T4393, First stab at Calendar day view sidebar

Test Plan: Open Calendar day view, sidebar should show today and the next 6 days, empty or not.

Reviewers: epriestley, #blessed_reviewers, chad

Reviewed By: epriestley, #blessed_reviewers

Subscribers: Korvin, epriestley

Maniphest Tasks: T4393

Differential Revision: https://secure.phabricator.com/D12742
---
 resources/celerity/map.php                    |   4 +-
 .../PhabricatorCalendarEventSearchEngine.php  |   4 +-
 src/infrastructure/time/PhabricatorTime.php   |  11 ++
 .../phui/calendar/PHUICalendarDayView.php     | 148 +++++++++++++++++-
 .../css/phui/calendar/phui-calendar-day.css   |  23 +++
 5 files changed, 183 insertions(+), 7 deletions(-)

diff --git a/resources/celerity/map.php b/resources/celerity/map.php
index 53b5069337..daa73b4445 100644
--- a/resources/celerity/map.php
+++ b/resources/celerity/map.php
@@ -119,7 +119,7 @@ return array(
     'rsrc/css/layout/phabricator-hovercard-view.css' => '44394670',
     'rsrc/css/layout/phabricator-side-menu-view.css' => 'c1db9e9c',
     'rsrc/css/layout/phabricator-source-code-view.css' => '2ceee894',
-    'rsrc/css/phui/calendar/phui-calendar-day.css' => '75b8cc4a',
+    'rsrc/css/phui/calendar/phui-calendar-day.css' => 'c2eb34ce',
     'rsrc/css/phui/calendar/phui-calendar-list.css' => 'c1d0ca59',
     'rsrc/css/phui/calendar/phui-calendar-month.css' => 'a92e47d2',
     'rsrc/css/phui/calendar/phui-calendar.css' => '8675968e',
@@ -773,7 +773,7 @@ return array(
     'phui-box-css' => '7b3a2eed',
     'phui-button-css' => 'de610129',
     'phui-calendar-css' => '8675968e',
-    'phui-calendar-day-css' => '75b8cc4a',
+    'phui-calendar-day-css' => 'c2eb34ce',
     'phui-calendar-list-css' => 'c1d0ca59',
     'phui-calendar-month-css' => 'a92e47d2',
     'phui-crumbs-view-css' => '594d719e',
diff --git a/src/applications/calendar/query/PhabricatorCalendarEventSearchEngine.php b/src/applications/calendar/query/PhabricatorCalendarEventSearchEngine.php
index 3f14adbae8..5eada843d3 100644
--- a/src/applications/calendar/query/PhabricatorCalendarEventSearchEngine.php
+++ b/src/applications/calendar/query/PhabricatorCalendarEventSearchEngine.php
@@ -70,7 +70,7 @@ final class PhabricatorCalendarEventSearchEngine
       if ($saved->getParameter('display') == 'month') {
         $next->modify('+1 month');
       } else if ($saved->getParameter('display') == 'day') {
-        $next->modify('+1 day');
+        $next->modify('+6 day');
       }
 
       $display_start = $start_day->format('U');
@@ -447,7 +447,7 @@ final class PhabricatorCalendarEventSearchEngine
     } else {
       $value = AphrontFormDateControlValue::newFromEpoch(
         $viewer,
-        PhabricatorTime::getNow());
+        PhabricatorTime::getTodayMidnightDateTime($viewer)->format('U'));
       $value->setEnabled(false);
     }
 
diff --git a/src/infrastructure/time/PhabricatorTime.php b/src/infrastructure/time/PhabricatorTime.php
index d1eb281e1c..d2866d99c2 100644
--- a/src/infrastructure/time/PhabricatorTime.php
+++ b/src/infrastructure/time/PhabricatorTime.php
@@ -58,4 +58,15 @@ final class PhabricatorTime {
     return $timestamp;
   }
 
+  public static function getTodayMidnightDateTime($viewer) {
+    $timezone = new DateTimeZone($viewer->getTimezoneIdentifier());
+    $today = new DateTime('@'.time());
+    $today->setTimeZone($timezone);
+    $year = $today->format('Y');
+    $month = $today->format('m');
+    $day = $today->format('d');
+    $today = new DateTime("{$year}-{$month}-{$day}", $timezone);
+    return $today;
+  }
+
 }
diff --git a/src/view/phui/calendar/PHUICalendarDayView.php b/src/view/phui/calendar/PHUICalendarDayView.php
index 533fa0f446..ed17f88ab6 100644
--- a/src/view/phui/calendar/PHUICalendarDayView.php
+++ b/src/view/phui/calendar/PHUICalendarDayView.php
@@ -117,12 +117,155 @@ final class PHUICalendarDayView extends AphrontView {
       ));
 
     $header = $this->renderDayViewHeader();
+    $sidebar = $this->renderSidebar();
 
-    $day_box = (new PHUIObjectBoxView())
+    $table_box = id(new PHUIObjectBoxView())
       ->setHeader($header)
       ->appendChild($table);
 
-    return $day_box;
+    $column1 = phutil_tag(
+      'div',
+        array(
+          'class' => 'pm',
+        ),
+        $sidebar);
+
+    $column2 = phutil_tag(
+      'div',
+        array(
+          'class' => 'pm',
+        ),
+        $table_box);
+
+    $layout = id(new AphrontMultiColumnView())
+      ->addColumn($column1, 'third')
+      ->addColumn($column2, 'thirds')
+      ->setFluidLayout(true)
+      ->setGutter(AphrontMultiColumnView::GUTTER_MEDIUM);
+
+    $wrap = phutil_tag(
+      'div',
+        array(
+          'class' => 'ml',
+        ),
+        $layout);
+
+    return phutil_tag(
+      'div',
+        array(),
+        array(
+          $wrap,
+        ));
+  }
+
+  private function renderSidebar() {
+    $this->events = msort($this->events, 'getEpochStart');
+    $week_of_boxes = $this->getWeekOfBoxes();
+    $filled_boxes = array();
+
+    foreach ($week_of_boxes as $box) {
+      $start = $box['start'];
+      $end = id(clone $start)->modify('+1 day');
+
+      $box = $box['box'];
+      $box_events = array();
+
+      foreach ($this->events as $event) {
+        if ($event->getEpochStart() >= $start->format('U') &&
+        $event->getEpochStart() < $end->format('U')) {
+          $box_events[] = $event;
+        }
+      }
+      $filled_boxes[] = $this->renderSidebarBox($box_events, $box);
+    }
+
+    return $filled_boxes;
+  }
+
+  private function renderSidebarBox($events, $box) {
+    $user = $this->user;
+    $rows = array();
+
+    foreach ($events as $key => $event) {
+      $uri = $event->getURI();
+      $name = $event->getName();
+      $time = id(AphrontFormDateControlValue::newFromEpoch(
+        $user,
+        $event->getEpochStart()))
+      ->getValueTime();
+
+      $name = phutil_tag(
+        'a',
+        array(
+          'href' => $uri,
+        ),
+        $name);
+
+      $name = phutil_tag(
+        'td',
+        array(
+          'class' => 'calendar-day-sidebar-column-name',
+        ),
+        $name);
+
+      $time = phutil_tag(
+        'td',
+        array(
+          'class' => 'calendar-day-sidebar-column-time',
+        ),
+        $time);
+
+      $rows[] = phutil_tag(
+        'tr',
+        array(
+          'class' => 'calendar-day-sidebar-row',
+        ),
+        array(
+          $name,
+          $time,
+        ));
+    }
+
+    $table = phutil_tag(
+      'table',
+      array(
+        'class' => 'calendar-day-sidebar-today-table',
+      ),
+      $rows);
+
+    $box->appendChild($table);
+    return $box;
+  }
+
+  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(
+        'box' => id(new PHUIObjectBoxView())->setHeaderText($title),
+        'start' => clone $box_start_time,
+        );
+
+      $box_start_time->modify('+1 day');
+    }
+    return $sidebar_day_boxes;
   }
 
   private function renderDayViewHeader() {
@@ -290,7 +433,6 @@ final class PHUICalendarDayView extends AphrontView {
     $events = msort($this->events, 'getEpochStart');
     $clusters = array();
 
-
     foreach ($events as $event) {
       $destination_cluster_key = null;
       $event_start = $event->getEpochStart();
diff --git a/webroot/rsrc/css/phui/calendar/phui-calendar-day.css b/webroot/rsrc/css/phui/calendar/phui-calendar-day.css
index bb07f8b8f8..6ac1c8436a 100644
--- a/webroot/rsrc/css/phui/calendar/phui-calendar-day.css
+++ b/webroot/rsrc/css/phui/calendar/phui-calendar-day.css
@@ -7,6 +7,29 @@
   width: 100%;
 }
 
+.calendar-day-sidebar-today-table {
+  width: 100%;
+  margin: 8px 0;
+}
+
+.calendar-day-sidebar-column-name {
+  text-align: left;
+  color: {$bluetext};
+  width: 60%;
+  padding: 4px 16px;
+}
+
+.calendar-day-sidebar-column-name a {
+  color: {$bluetext};
+}
+
+.calendar-day-sidebar-column-time {
+  color: {$bluetext};
+  text-align: right;
+  width: 40%;
+  padding: 4px 16px;
+}
+
 .phui-calendar-day-hour {
   width: 60px;
   color: {$lightgreytext};