Build a basic calendar view
Summary:
This is a very small step toward building a Status and possibly an Oncall tool.
Build a calendar view which renders months.
Much of my hesitance to bang these tools out is that dealing with
dates/calendaring is basically horrible, so I'm trying to ease into it.
This calendar is locale-aware and all that jazz.
Test Plan:
- See:
https://secure.phabricator.com/file/view/PHID-FILE-c07a9c663a7d040d2529/
- Verified that months have the right number of days, today is the right day
of the week, months begin on the day after previous months end on, etc.
Reviewed By: aran
Reviewers: jungejason, tuomaspelkonen, aran
Commenters: cwbeck, jungejason
CC: blair, aran, epriestley, cwbeck, jungejason
Differential Revision: 791
2011-08-08 03:26:31 +02:00
|
|
|
<?php
|
|
|
|
|
|
|
|
/*
|
2012-05-03 09:21:47 +02:00
|
|
|
* Copyright 2012 Facebook, Inc.
|
Build a basic calendar view
Summary:
This is a very small step toward building a Status and possibly an Oncall tool.
Build a calendar view which renders months.
Much of my hesitance to bang these tools out is that dealing with
dates/calendaring is basically horrible, so I'm trying to ease into it.
This calendar is locale-aware and all that jazz.
Test Plan:
- See:
https://secure.phabricator.com/file/view/PHID-FILE-c07a9c663a7d040d2529/
- Verified that months have the right number of days, today is the right day
of the week, months begin on the day after previous months end on, etc.
Reviewed By: aran
Reviewers: jungejason, tuomaspelkonen, aran
Commenters: cwbeck, jungejason
CC: blair, aran, epriestley, cwbeck, jungejason
Differential Revision: 791
2011-08-08 03:26:31 +02:00
|
|
|
*
|
|
|
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
|
|
* you may not use this file except in compliance with the License.
|
|
|
|
* You may obtain a copy of the License at
|
|
|
|
*
|
|
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
|
|
|
*
|
|
|
|
* Unless required by applicable law or agreed to in writing, software
|
|
|
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
|
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
|
|
* See the License for the specific language governing permissions and
|
|
|
|
* limitations under the License.
|
|
|
|
*/
|
|
|
|
|
|
|
|
final class AphrontCalendarMonthView extends AphrontView {
|
|
|
|
|
|
|
|
private $user;
|
|
|
|
private $month;
|
|
|
|
private $year;
|
2012-05-03 09:21:47 +02:00
|
|
|
private $holidays = array();
|
2012-05-21 19:24:23 +02:00
|
|
|
private $events = array();
|
Build a basic calendar view
Summary:
This is a very small step toward building a Status and possibly an Oncall tool.
Build a calendar view which renders months.
Much of my hesitance to bang these tools out is that dealing with
dates/calendaring is basically horrible, so I'm trying to ease into it.
This calendar is locale-aware and all that jazz.
Test Plan:
- See:
https://secure.phabricator.com/file/view/PHID-FILE-c07a9c663a7d040d2529/
- Verified that months have the right number of days, today is the right day
of the week, months begin on the day after previous months end on, etc.
Reviewed By: aran
Reviewers: jungejason, tuomaspelkonen, aran
Commenters: cwbeck, jungejason
CC: blair, aran, epriestley, cwbeck, jungejason
Differential Revision: 791
2011-08-08 03:26:31 +02:00
|
|
|
|
|
|
|
public function setUser(PhabricatorUser $user) {
|
|
|
|
$this->user = $user;
|
|
|
|
return $this;
|
|
|
|
}
|
|
|
|
|
2012-05-21 19:24:23 +02:00
|
|
|
public function addEvent(AphrontCalendarEventView $event) {
|
|
|
|
$this->events[] = $event;
|
|
|
|
return $this;
|
|
|
|
}
|
|
|
|
|
2012-05-03 09:21:47 +02:00
|
|
|
public function setHolidays(array $holidays) {
|
|
|
|
assert_instances_of($holidays, 'PhabricatorCalendarHoliday');
|
|
|
|
$this->holidays = mpull($holidays, null, 'getDay');
|
|
|
|
return $this;
|
|
|
|
}
|
|
|
|
|
Build a basic calendar view
Summary:
This is a very small step toward building a Status and possibly an Oncall tool.
Build a calendar view which renders months.
Much of my hesitance to bang these tools out is that dealing with
dates/calendaring is basically horrible, so I'm trying to ease into it.
This calendar is locale-aware and all that jazz.
Test Plan:
- See:
https://secure.phabricator.com/file/view/PHID-FILE-c07a9c663a7d040d2529/
- Verified that months have the right number of days, today is the right day
of the week, months begin on the day after previous months end on, etc.
Reviewed By: aran
Reviewers: jungejason, tuomaspelkonen, aran
Commenters: cwbeck, jungejason
CC: blair, aran, epriestley, cwbeck, jungejason
Differential Revision: 791
2011-08-08 03:26:31 +02:00
|
|
|
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()!");
|
|
|
|
}
|
|
|
|
|
2012-05-21 19:24:23 +02:00
|
|
|
$events = msort($this->events, 'getEpochStart');
|
|
|
|
|
Build a basic calendar view
Summary:
This is a very small step toward building a Status and possibly an Oncall tool.
Build a calendar view which renders months.
Much of my hesitance to bang these tools out is that dealing with
dates/calendaring is basically horrible, so I'm trying to ease into it.
This calendar is locale-aware and all that jazz.
Test Plan:
- See:
https://secure.phabricator.com/file/view/PHID-FILE-c07a9c663a7d040d2529/
- Verified that months have the right number of days, today is the right day
of the week, months begin on the day after previous months end on, etc.
Reviewed By: aran
Reviewers: jungejason, tuomaspelkonen, aran
Commenters: cwbeck, jungejason
CC: blair, aran, epriestley, cwbeck, jungejason
Differential Revision: 791
2011-08-08 03:26:31 +02:00
|
|
|
$days = $this->getDatesInMonth();
|
|
|
|
|
|
|
|
require_celerity_resource('aphront-calendar-view-css');
|
|
|
|
|
|
|
|
$first = reset($days);
|
|
|
|
$empty = $first->format('w');
|
|
|
|
|
|
|
|
$markup = array();
|
|
|
|
|
2012-05-21 19:24:23 +02:00
|
|
|
$empty_box =
|
|
|
|
'<div class="aphront-calendar-day aphront-calendar-empty">'.
|
|
|
|
'</div>';
|
|
|
|
|
Build a basic calendar view
Summary:
This is a very small step toward building a Status and possibly an Oncall tool.
Build a calendar view which renders months.
Much of my hesitance to bang these tools out is that dealing with
dates/calendaring is basically horrible, so I'm trying to ease into it.
This calendar is locale-aware and all that jazz.
Test Plan:
- See:
https://secure.phabricator.com/file/view/PHID-FILE-c07a9c663a7d040d2529/
- Verified that months have the right number of days, today is the right day
of the week, months begin on the day after previous months end on, etc.
Reviewed By: aran
Reviewers: jungejason, tuomaspelkonen, aran
Commenters: cwbeck, jungejason
CC: blair, aran, epriestley, cwbeck, jungejason
Differential Revision: 791
2011-08-08 03:26:31 +02:00
|
|
|
for ($ii = 0; $ii < $empty; $ii++) {
|
2012-05-21 19:24:23 +02:00
|
|
|
$markup[] = $empty_box;
|
Build a basic calendar view
Summary:
This is a very small step toward building a Status and possibly an Oncall tool.
Build a calendar view which renders months.
Much of my hesitance to bang these tools out is that dealing with
dates/calendaring is basically horrible, so I'm trying to ease into it.
This calendar is locale-aware and all that jazz.
Test Plan:
- See:
https://secure.phabricator.com/file/view/PHID-FILE-c07a9c663a7d040d2529/
- Verified that months have the right number of days, today is the right day
of the week, months begin on the day after previous months end on, etc.
Reviewed By: aran
Reviewers: jungejason, tuomaspelkonen, aran
Commenters: cwbeck, jungejason
CC: blair, aran, epriestley, cwbeck, jungejason
Differential Revision: 791
2011-08-08 03:26:31 +02:00
|
|
|
}
|
|
|
|
|
2012-05-21 20:59:12 +02:00
|
|
|
$show_events = array();
|
|
|
|
|
Build a basic calendar view
Summary:
This is a very small step toward building a Status and possibly an Oncall tool.
Build a calendar view which renders months.
Much of my hesitance to bang these tools out is that dealing with
dates/calendaring is basically horrible, so I'm trying to ease into it.
This calendar is locale-aware and all that jazz.
Test Plan:
- See:
https://secure.phabricator.com/file/view/PHID-FILE-c07a9c663a7d040d2529/
- Verified that months have the right number of days, today is the right day
of the week, months begin on the day after previous months end on, etc.
Reviewed By: aran
Reviewers: jungejason, tuomaspelkonen, aran
Commenters: cwbeck, jungejason
CC: blair, aran, epriestley, cwbeck, jungejason
Differential Revision: 791
2011-08-08 03:26:31 +02:00
|
|
|
foreach ($days as $day) {
|
2012-05-03 09:21:47 +02:00
|
|
|
$holiday = idx($this->holidays, $day->format('Y-m-d'));
|
2012-05-21 19:24:23 +02:00
|
|
|
$class = 'aphront-calendar-day';
|
2012-05-03 09:21:47 +02:00
|
|
|
$weekday = $day->format('w');
|
|
|
|
if ($holiday || $weekday == 0 || $weekday == 6) {
|
|
|
|
$class .= ' aphront-calendar-not-work-day';
|
|
|
|
}
|
2012-05-21 19:24:23 +02:00
|
|
|
|
|
|
|
$day->setTime(0, 0, 0);
|
|
|
|
$epoch_start = $day->format('U');
|
|
|
|
|
2012-05-21 20:59:12 +02:00
|
|
|
$day->setTime(24, 0, 0);
|
2012-05-21 19:24:23 +02:00
|
|
|
$epoch_end = $day->format('U');
|
|
|
|
|
2012-05-21 20:59:12 +02:00
|
|
|
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">'.
|
|
|
|
' '.
|
|
|
|
'</div>');
|
|
|
|
}
|
|
|
|
|
2012-05-21 19:24:23 +02:00
|
|
|
foreach ($events as $event) {
|
2012-05-21 20:59:12 +02:00
|
|
|
if ($event->getEpochStart() >= $epoch_end) {
|
2012-05-21 19:24:23 +02:00
|
|
|
// This list is sorted, so we can stop looking.
|
|
|
|
break;
|
|
|
|
}
|
2012-05-21 20:59:12 +02:00
|
|
|
if ($event->getEpochStart() < $epoch_end &&
|
|
|
|
$event->getEpochEnd() > $epoch_start) {
|
|
|
|
$show_events[$event->getUserPHID()] = $this->renderEvent(
|
2012-05-21 19:24:23 +02:00
|
|
|
$event,
|
|
|
|
$day,
|
|
|
|
$epoch_start,
|
|
|
|
$epoch_end);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
$holiday_markup = null;
|
|
|
|
if ($holiday) {
|
2012-05-21 20:59:12 +02:00
|
|
|
$name = phutil_escape_html($holiday->getName());
|
2012-05-21 19:24:23 +02:00
|
|
|
$holiday_markup =
|
2012-05-21 20:59:12 +02:00
|
|
|
'<div class="aphront-calendar-holiday" title="'.$name.'">'.
|
|
|
|
$name.
|
2012-05-21 19:24:23 +02:00
|
|
|
'</div>';
|
|
|
|
}
|
|
|
|
|
Build a basic calendar view
Summary:
This is a very small step toward building a Status and possibly an Oncall tool.
Build a calendar view which renders months.
Much of my hesitance to bang these tools out is that dealing with
dates/calendaring is basically horrible, so I'm trying to ease into it.
This calendar is locale-aware and all that jazz.
Test Plan:
- See:
https://secure.phabricator.com/file/view/PHID-FILE-c07a9c663a7d040d2529/
- Verified that months have the right number of days, today is the right day
of the week, months begin on the day after previous months end on, etc.
Reviewed By: aran
Reviewers: jungejason, tuomaspelkonen, aran
Commenters: cwbeck, jungejason
CC: blair, aran, epriestley, cwbeck, jungejason
Differential Revision: 791
2011-08-08 03:26:31 +02:00
|
|
|
$markup[] =
|
2012-05-03 09:21:47 +02:00
|
|
|
'<div class="'.$class.'">'.
|
2012-05-21 19:24:23 +02:00
|
|
|
'<div class="aphront-calendar-date-number">'.
|
|
|
|
$day->format('j').
|
|
|
|
'</div>'.
|
2012-05-21 20:59:12 +02:00
|
|
|
$holiday_markup.
|
2012-05-21 19:24:23 +02:00
|
|
|
implode("\n", $show_events).
|
Build a basic calendar view
Summary:
This is a very small step toward building a Status and possibly an Oncall tool.
Build a calendar view which renders months.
Much of my hesitance to bang these tools out is that dealing with
dates/calendaring is basically horrible, so I'm trying to ease into it.
This calendar is locale-aware and all that jazz.
Test Plan:
- See:
https://secure.phabricator.com/file/view/PHID-FILE-c07a9c663a7d040d2529/
- Verified that months have the right number of days, today is the right day
of the week, months begin on the day after previous months end on, etc.
Reviewed By: aran
Reviewers: jungejason, tuomaspelkonen, aran
Commenters: cwbeck, jungejason
CC: blair, aran, epriestley, cwbeck, jungejason
Differential Revision: 791
2011-08-08 03:26:31 +02:00
|
|
|
'</div>';
|
|
|
|
}
|
|
|
|
|
|
|
|
$table = array();
|
|
|
|
$rows = array_chunk($markup, 7);
|
|
|
|
foreach ($rows as $row) {
|
|
|
|
$table[] = '<tr>';
|
|
|
|
while (count($row) < 7) {
|
2012-05-21 19:24:23 +02:00
|
|
|
$row[] = $empty_box;
|
Build a basic calendar view
Summary:
This is a very small step toward building a Status and possibly an Oncall tool.
Build a calendar view which renders months.
Much of my hesitance to bang these tools out is that dealing with
dates/calendaring is basically horrible, so I'm trying to ease into it.
This calendar is locale-aware and all that jazz.
Test Plan:
- See:
https://secure.phabricator.com/file/view/PHID-FILE-c07a9c663a7d040d2529/
- Verified that months have the right number of days, today is the right day
of the week, months begin on the day after previous months end on, etc.
Reviewed By: aran
Reviewers: jungejason, tuomaspelkonen, aran
Commenters: cwbeck, jungejason
CC: blair, aran, epriestley, cwbeck, jungejason
Differential Revision: 791
2011-08-08 03:26:31 +02:00
|
|
|
}
|
|
|
|
foreach ($row as $cell) {
|
|
|
|
$table[] = '<td>'.$cell.'</td>';
|
|
|
|
}
|
|
|
|
$table[] = '</tr>';
|
|
|
|
}
|
|
|
|
$table =
|
|
|
|
'<table class="aphront-calendar-view">'.
|
|
|
|
'<tr class="aphront-calendar-month-year-header">'.
|
|
|
|
'<th colspan="7">'.$first->format('F Y').'</th>'.
|
|
|
|
'</tr>'.
|
|
|
|
'<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;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* 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;
|
|
|
|
|
|
|
|
// Find the year and month numbers of the following month, so we can
|
|
|
|
// determine when this month ends.
|
|
|
|
$next_year = $year;
|
|
|
|
$next_month = $month + 1;
|
|
|
|
if ($next_month == 13) {
|
|
|
|
$next_year = $year + 1;
|
|
|
|
$next_month = 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
$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;
|
|
|
|
}
|
2012-05-21 19:24:23 +02:00
|
|
|
|
|
|
|
private function renderEvent(
|
|
|
|
AphrontCalendarEventView $event,
|
|
|
|
DateTime $day,
|
|
|
|
$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';
|
2012-05-21 20:59:12 +02:00
|
|
|
$when[] = 'Ends '.phabricator_datetime($event_end, $user);
|
2012-05-21 19:24:23 +02:00
|
|
|
} else {
|
|
|
|
$when[] = 'Ends at '.phabricator_time($event_end, $user);
|
|
|
|
}
|
|
|
|
|
|
|
|
Javelin::initBehavior('phabricator-tooltips');
|
|
|
|
|
|
|
|
$info = $event->getName();
|
|
|
|
if ($event->getDescription()) {
|
|
|
|
$info .= "\n\n".$event->getDescription();
|
|
|
|
}
|
|
|
|
|
|
|
|
$text_div = javelin_render_tag(
|
|
|
|
'div',
|
|
|
|
array(
|
|
|
|
'sigil' => 'has-tooltip',
|
|
|
|
'meta' => array(
|
|
|
|
'tip' => $info."\n\n".implode("\n", $when),
|
|
|
|
'size' => 240,
|
|
|
|
),
|
|
|
|
'class' => 'aphront-calendar-event-text',
|
|
|
|
),
|
|
|
|
phutil_escape_html(phutil_utf8_shorten($event->getName(), 32)));
|
|
|
|
|
|
|
|
return javelin_render_tag(
|
|
|
|
'div',
|
|
|
|
array(
|
|
|
|
'class' => implode(' ', $classes),
|
|
|
|
),
|
|
|
|
$text_div);
|
|
|
|
}
|
|
|
|
|
Build a basic calendar view
Summary:
This is a very small step toward building a Status and possibly an Oncall tool.
Build a calendar view which renders months.
Much of my hesitance to bang these tools out is that dealing with
dates/calendaring is basically horrible, so I'm trying to ease into it.
This calendar is locale-aware and all that jazz.
Test Plan:
- See:
https://secure.phabricator.com/file/view/PHID-FILE-c07a9c663a7d040d2529/
- Verified that months have the right number of days, today is the right day
of the week, months begin on the day after previous months end on, etc.
Reviewed By: aran
Reviewers: jungejason, tuomaspelkonen, aran
Commenters: cwbeck, jungejason
CC: blair, aran, epriestley, cwbeck, jungejason
Differential Revision: 791
2011-08-08 03:26:31 +02:00
|
|
|
}
|