Page MenuHomestyx hydra

No OneTemporary

diff --git a/src/view/phui/calendar/PHUICalendarDayView.php b/src/view/phui/calendar/PHUICalendarDayView.php
index 7d32866cea..30d35e93fd 100644
--- a/src/view/phui/calendar/PHUICalendarDayView.php
+++ b/src/view/phui/calendar/PHUICalendarDayView.php
@@ -1,594 +1,469 @@
<?php
final class PHUICalendarDayView extends AphrontView {
private $rangeStart;
private $rangeEnd;
private $day;
private $month;
private $year;
private $browseURI;
private $events = array();
- private $todayEvents = array();
private $jsTodayEvents = array();
private $allDayEvents = array();
public function addEvent(AphrontCalendarEventView $event) {
$this->events[] = $event;
return $this;
}
public function setBrowseURI($browse_uri) {
$this->browseURI = $browse_uri;
return $this;
}
private function getBrowseURI() {
return $this->browseURI;
}
public function __construct(
$range_start,
$range_end,
$year,
$month,
$day = null) {
$this->rangeStart = $range_start;
$this->rangeEnd = $range_end;
$this->day = $day;
$this->month = $month;
$this->year = $year;
}
public function render() {
require_celerity_resource('phui-calendar-day-css');
$hours = $this->getHoursOfDay();
$js_hours = array();
foreach ($hours as $hour) {
$js_hours[] = array(
'hour' => $hour->format('G'),
'hour_meridian' => $hour->format('g A'),
);
}
- $js_hourly_events = array();
- $hourly_events = array();
-
$first_event_hour = null;
+ $js_hourly_events = array();
+ $js_today_all_day_events = array();
+
$all_day_events = $this->getAllDayEvents();
- $today_all_day_events = array();
$day_start = $this->getDateTime();
$day_end = id(clone $day_start)->modify('+1 day');
$day_start_epoch = $day_start->format('U');
$day_end_epoch = $day_end->format('U') - 1;
foreach ($all_day_events as $all_day_event) {
$all_day_start = $all_day_event->getEpochStart();
$all_day_end = $all_day_event->getEpochEnd();
if ($all_day_start < $day_end_epoch && $all_day_end > $day_start_epoch) {
- $today_all_day_events[] = $all_day_event;
+ $js_today_all_day_events[] = array(
+ 'name' => $all_day_event->getName(),
+ 'id' => $all_day_event->getEventID(),
+ 'viewerIsInvited' => $all_day_event->getViewerIsInvited(),
+ 'uri' => $all_day_event->getURI(),
+ );
}
}
foreach ($hours as $hour) {
$current_hour_events = array();
$hour_start = $hour->format('U');
$hour_end = id(clone $hour)->modify('+1 hour')->format('U');
foreach ($this->events as $event) {
if ($event->getIsAllDay()) {
continue;
}
if (($hour == $day_start &&
$event->getEpochStart() <= $hour_start &&
$event->getEpochEnd() > $day_start_epoch) ||
($event->getEpochStart() >= $hour_start
&& $event->getEpochStart() < $hour_end)) {
$current_hour_events[] = $event;
- $this->todayEvents[] = $event;
$this->jsTodayEvents[] = array(
'eventStartEpoch' => $event->getEpochStart(),
'eventEndEpoch' => $event->getEpochEnd(),
'eventName' => $event->getName(),
'eventID' => $event->getEventID(),
'viewerIsInvited' => $event->getViewerIsInvited(),
'uri' => $event->getURI(),
);
}
}
foreach ($current_hour_events as $event) {
$day_start_epoch = $this->getDateTime()->format('U');
$event_start = max($event->getEpochStart(), $day_start_epoch);
$event_end = min($event->getEpochEnd(), $day_end_epoch);
$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);
if ($first_event_hour === null) {
$first_event_hour = $hour;
}
$js_hourly_events[] = array(
'eventStartEpoch' => $event->getEpochStart(),
'eventEndEpoch' => $event->getEpochEnd(),
'eventName' => $event->getName(),
'eventID' => $event->getEventID(),
'viewerIsInvited' => $event->getViewerIsInvited(),
'uri' => $event->getURI(),
'hour' => $hour->format('G'),
'offset' => '0',
'width' => '100%',
'top' => $top.'%',
'height' => $height.'%',
);
-
- $hourly_events[$event->getEventID()] = array(
- 'hour' => $hour,
- 'event' => $event,
- 'offset' => '0',
- 'width' => '100%',
- 'top' => $top.'%',
- 'height' => $height.'%',
- );
- }
- }
-
- $clusters = $this->findTodayClusters();
- foreach ($clusters as $cluster) {
- $hourly_events = $this->updateEventsFromCluster(
- $cluster,
- $hourly_events);
- }
-
- $rows = array();
-
- foreach ($hours as $hour) {
- $early_hours = array(8);
- if ($first_event_hour) {
- $early_hours[] = $first_event_hour->format('G');
- }
- if ($hour->format('G') < min($early_hours)) {
- continue;
}
-
- $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'),
- $rows);
-
- $all_day_event_box = new PHUIBoxView();
- foreach ($today_all_day_events as $all_day_event) {
- $all_day_event_box->appendChild(
- $this->drawAllDayEvent($all_day_event));
}
$header = $this->renderDayViewHeader();
$sidebar = $this->renderSidebar();
$warnings = $this->getQueryRangeWarning();
+ $table_id = celerity_generate_unique_node_id();
+
+ $table_wrapper = phutil_tag(
+ 'div',
+ array(
+ 'id' => $table_id,
+ ),
+ '');
+
Javelin::initBehavior(
'day-view',
array(
+ 'allDayEvents' => $js_today_all_day_events,
'todayEvents' => $this->jsTodayEvents,
'hourlyEvents' => $js_hourly_events,
'hours' => $js_hours,
'firstEventHour' => $first_event_hour->format('G'),
+ 'tableID' => $table_id,
));
$table_box = id(new PHUIObjectBoxView())
->setHeader($header)
- ->appendChild($all_day_event_box)
- ->appendChild($table)
+ ->appendChild($table_wrapper)
->setFormErrors($warnings)
->setFlush(true);
$layout = id(new AphrontMultiColumnView())
->addColumn($sidebar, 'third')
->addColumn($table_box, 'thirds phui-day-view-column')
->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 getQueryRangeWarning() {
$errors = array();
$range_start_epoch = $this->rangeStart->getEpoch();
$range_end_epoch = $this->rangeEnd->getEpoch();
$day_start = $this->getDateTime();
$day_end = id(clone $day_start)->modify('+1 day');
$day_start = $day_start->format('U');
$day_end = $day_end->format('U') - 1;
if (($range_start_epoch != null &&
$range_start_epoch < $day_end &&
$range_start_epoch > $day_start) ||
($range_end_epoch != null &&
$range_end_epoch < $day_end &&
$range_end_epoch > $day_start)) {
$errors[] = pht('Part of the day is out of range');
}
if (($this->rangeEnd->getEpoch() != null &&
$this->rangeEnd->getEpoch() < $day_start) ||
($this->rangeStart->getEpoch() != null &&
$this->rangeStart->getEpoch() > $day_end)) {
$errors[] = pht('Day is out of query range');
}
return $errors;
}
private function renderSidebar() {
$this->events = msort($this->events, 'getEpochStart');
$week_of_boxes = $this->getWeekOfBoxes();
$filled_boxes = array();
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) {
$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,
$day_box['title']);
}
return $filled_boxes;
}
private function renderSidebarBox($events, $title) {
$widget = id(new PHUICalendarWidgetView())
->addClass('calendar-day-view-sidebar');
$list = id(new PHUICalendarListView())
->setUser($this->user)
->setView('day');
if (count($events) == 0) {
$list->showBlankState(true);
} else {
$sorted_events = msort($events, 'getEpochStart');
foreach ($sorted_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;
$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);
}
$display_day = $this->getDateTime();
$header_text = $display_day->format('l, F j, Y');
$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 drawAllDayEvent(AphrontCalendarEventView $event) {
- $class = 'day-view-all-day';
- if ($event->getViewerIsInvited()) {
- $class = $class.' viewer-invited-day-event';
- }
-
- $name = phutil_tag(
- 'a',
- array(
- 'class' => $class,
- 'href' => $event->getURI(),
- ),
- $event->getName());
-
- $all_day_label = phutil_tag(
- 'span',
- array(
- 'class' => 'phui-calendar-all-day-label',
- ),
- pht('All Day'));
-
- $div = phutil_tag(
- 'div',
- array(
- 'class' => 'phui-calendar-day-event',
- ),
- array(
- $all_day_label,
- $name,
- ));
-
- return $div;
- }
-
- private function drawEvent(
- AphrontCalendarEventView $event,
- $offset,
- $width,
- $top,
- $height) {
-
- $class = 'phui-calendar-day-event-link';
- if ($event->getViewerIsInvited()) {
- $class = $class.' viewer-invited-day-event';
- }
-
- $name = phutil_tag(
- 'a',
- array(
- 'class' => $class,
- '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;
- }
-
// 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 findTodayClusters() {
$events = msort($this->todayEvents, 'getEpochStart');
$clusters = array();
foreach ($events as $event) {
$destination_cluster_key = null;
$event_start = $event->getEpochStart() - (30 * 60);
$event_end = $event->getEpochEnd() + (30 * 60);
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/webroot/rsrc/js/application/calendar/behavior-day-view.js b/webroot/rsrc/js/application/calendar/behavior-day-view.js
index f37714c04f..9c42b7f719 100644
--- a/webroot/rsrc/js/application/calendar/behavior-day-view.js
+++ b/webroot/rsrc/js/application/calendar/behavior-day-view.js
@@ -1,182 +1,215 @@
/**
* @provides javelin-behavior-day-view
*/
JX.behavior('day-view', function(config) {
var hours = config.hours;
var first_event_hour = config.firstEventHour;
var hourly_events = config.hourlyEvents;
var today_events = config.todayEvents;
+ var today_all_day_events = config.allDayEvents;
+ var table_wrapper = JX.$(config.tableID);
function findTodayClusters() {
var events = today_events.sort(function(x, y){
return (x.eventStartEpoch - y.eventStartEpoch);
});
var clusters = [];
for (var i=0; i < events.length; i++) {
var today_event = events[i];
var destination_cluster_index = null;
var event_start = today_event.eventStartEpoch - (30*60);
var event_end = today_event.eventEndEpoch + (30*60);
for (var j=0; j < clusters.length; j++) {
var cluster = clusters[j];
for(var k=0; k < cluster.length; k++) {
var clustered_event = cluster[k];
var compare_event_start = clustered_event.eventStartEpoch;
var compare_event_end = clustered_event.eventEndEpoch;
if (event_start < compare_event_end &&
event_end > compare_event_start) {
destination_cluster_index = j;
break;
}
}
if (destination_cluster_index !== null) {
break;
}
}
if (destination_cluster_index !== null) {
clusters[destination_cluster_index].push(today_event);
destination_cluster_index = null;
} else {
var next_cluster = [];
next_cluster.push(today_event);
clusters.push(next_cluster);
}
}
return clusters;
}
function updateEventsFromCluster(cluster, hourly_events) {
var cluster_size = cluster.length;
var n = 0;
for(var i=0; i < cluster.length; i++) {
var cluster_member = cluster[i];
var event_id = cluster_member.eventID;
var offset = ((n / cluster_size) * 100) + '%';
var width = ((1 / cluster_size) * 100) + '%';
for (var j=0; j < hourly_events.length; j++) {
if (hourly_events[j].eventID == event_id) {
hourly_events[j]['offset'] = offset;
hourly_events[j]['width'] = width;
}
}
n++;
}
return hourly_events;
}
- function drawEvent(
- start,
- end,
- name,
- viewerIsInvited,
- uri,
- id,
- offset,
- width,
- top,
- height) {
+ function drawEvent(hourly_event) {
+ var name = hourly_event['eventName'];
+ var viewerIsInvited = hourly_event['viewerIsInvited'];
+ var offset = hourly_event['offset'];
+ var width = hourly_event['width'];
+ var top = hourly_event['top'];
+ var height = hourly_event['height'];
+ var uri = hourly_events['uri'];
var link_class = 'phui-calendar-day-event-link';
+
if (viewerIsInvited) {
link_class = link_class + ' viewer-invited-day-event';
}
var name_link = JX.$N(
'a',
{
className : link_class,
href: uri
},
name);
var div = JX.$N(
'div',
{
className: 'phui-calendar-day-event',
style: {
left: offset,
width: width,
top: top,
height: height
}
},
name_link);
return div;
}
+ function drawAllDayEvent(
+ viewerIsInvited,
+ uri,
+ name) {
+ var class_name = 'day-view-all-day';
+ if (viewerIsInvited) {
+ class_name = class_name + ' viewer-invited-day-event';
+ }
+
+ name = JX.$N(
+ 'a',
+ {
+ className: class_name,
+ href: uri
+ },
+ name);
+
+ var all_day_label = JX.$N(
+ 'span',
+ {className: 'phui-calendar-all-day-label'},
+ 'All Day');
+
+ var div_all_day = JX.$N(
+ 'div',
+ {className: 'phui-calendar-day-event'},
+ [all_day_label, name]);
+
+ return div_all_day;
+ }
+
function drawRows() {
var rows = [];
var early_hours = [8];
if (first_event_hour) {
early_hours.push(first_event_hour);
}
var min_early_hour = Math.min(early_hours[0], early_hours[1]);
for(var i=0; i < hours.length; i++) {
if (hours[i]['hour'] < min_early_hour) {
continue;
}
var drawn_hourly_events = [];
var cell_time = JX.$N(
'td',
{className: 'phui-calendar-day-hour'},
hours[i]['hour_meridian']);
for (var j=0; j < hourly_events.length; j++) {
if (hourly_events[j]['hour'] == hours[i]['hour']) {
- drawn_hourly_events.push(
- drawEvent(
- hourly_events[j]['eventStartEpoch'],
- hourly_events[j]['eventEndEpoch'],
- hourly_events[j]['eventName'],
- hourly_events[j]['eventID'],
- hourly_events[j]['viewerIsInvited'],
- hourly_events[j]['hour'],
- hourly_events[j]['offset'],
- hourly_events[j]['width'],
- hourly_events[j]['top'],
- hourly_events[j]['height']
- )
- );
+ drawn_hourly_events.push(drawEvent(hourly_events[j]));
}
}
var cell_event = JX.$N(
'td',
{
className: 'phui-calendar-day-events'
},
drawn_hourly_events);
var row = JX.$N(
'tr',
{},
[cell_time, cell_event]);
rows.push(row);
}
return rows;
}
var today_clusters = findTodayClusters();
for(var i=0; i < today_clusters.length; i++) {
hourly_events = updateEventsFromCluster(today_clusters[i], hourly_events);
}
var rows = drawRows();
+
+ var all_day_events = [];
+ for(i=0; i < today_all_day_events.length; i++) {
+ var all_day_event = today_all_day_events[i];
+ all_day_events.push(drawAllDayEvent(
+ all_day_event['viewerIsInvited'],
+ all_day_event['uri'],
+ all_day_event['name']));
+ }
+
+ var table = JX.$N(
+ 'table',
+ {className: 'phui-calendar-day-view'},
+ rows);
+
+ JX.DOM.setContent(table_wrapper, [all_day_events, table]);
});

File Metadata

Mime Type
text/x-diff
Expires
Thu, Jul 24, 2:14 PM (1 d, 13 h)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
182735
Default Alt Text
(23 KB)

Event Timeline