1
0
Fork 0
mirror of https://we.phorge.it/source/phorge.git synced 2024-11-22 14:52:41 +01:00

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
This commit is contained in:
epriestley 2011-08-07 18:26:31 -07:00
parent fa49c6c52d
commit e35d72f489
10 changed files with 316 additions and 0 deletions

View file

@ -16,6 +16,15 @@ celerity_register_resource_map(array(
),
'disk' => '/rsrc/css/aphront/attached-file-view.css',
),
'aphront-calendar-view-css' =>
array(
'uri' => '/res/7036c676/rsrc/css/aphront/calendar-view.css',
'type' => 'css',
'requires' =>
array(
),
'disk' => '/rsrc/css/aphront/calendar-view.css',
),
'aphront-contextbar-view-css' =>
array(
'uri' => '/res/3e2f3045/rsrc/css/aphront/context-bar.css',

View file

@ -15,6 +15,7 @@ phutil_register_library_map(array(
'AphrontApplicationConfiguration' => 'aphront/applicationconfiguration',
'AphrontAttachedFileView' => 'view/control/attachedfile',
'AphrontCSRFException' => 'aphront/exception/csrf',
'AphrontCalendarMonthView' => 'applications/calendar/view/month',
'AphrontContextBarView' => 'view/layout/contextbar',
'AphrontController' => 'aphront/controller',
'AphrontCrumbsView' => 'view/layout/crumbs',
@ -301,6 +302,8 @@ phutil_register_library_map(array(
'ManiphestView' => 'applications/maniphest/view/base',
'Phabricator404Controller' => 'applications/base/controller/404',
'PhabricatorAuthController' => 'applications/auth/controller/base',
'PhabricatorCalendarBrowseController' => 'applications/calendar/controller/browse',
'PhabricatorCalendarController' => 'applications/calendar/controller/base',
'PhabricatorConduitAPIController' => 'applications/conduit/controller/api',
'PhabricatorConduitCertificateToken' => 'applications/conduit/storage/token',
'PhabricatorConduitConnectionLog' => 'applications/conduit/storage/connectionlog',
@ -664,6 +667,7 @@ phutil_register_library_map(array(
'AphrontAjaxResponse' => 'AphrontResponse',
'AphrontAttachedFileView' => 'AphrontView',
'AphrontCSRFException' => 'AphrontException',
'AphrontCalendarMonthView' => 'AphrontView',
'AphrontContextBarView' => 'AphrontView',
'AphrontCrumbsView' => 'AphrontView',
'AphrontDefaultApplicationConfiguration' => 'AphrontApplicationConfiguration',
@ -873,6 +877,8 @@ phutil_register_library_map(array(
'ManiphestView' => 'AphrontView',
'Phabricator404Controller' => 'PhabricatorController',
'PhabricatorAuthController' => 'PhabricatorController',
'PhabricatorCalendarBrowseController' => 'PhabricatorCalendarController',
'PhabricatorCalendarController' => 'PhabricatorController',
'PhabricatorConduitAPIController' => 'PhabricatorConduitController',
'PhabricatorConduitCertificateToken' => 'PhabricatorConduitDAO',
'PhabricatorConduitConnectionLog' => 'PhabricatorConduitDAO',

View file

@ -356,6 +356,10 @@ class AphrontDefaultApplicationConfiguration
'preview/$' => 'PhrictionDocumentPreviewController',
'diff/(?P<id>\d+)/$' => 'PhrictionDiffController',
),
'/calendar/' => array(
'$' => 'PhabricatorCalendarBrowseController',
),
);
}

View file

@ -0,0 +1,43 @@
<?php
/*
* Copyright 2011 Facebook, Inc.
*
* 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.
*/
abstract class PhabricatorCalendarController extends PhabricatorController {
public function buildStandardPageResponse($view, array $data) {
$page = $this->buildStandardPageView();
$page->setApplicationName('Calendar');
$page->setBaseURI('/calendar/');
$page->setTitle(idx($data, 'title'));
// Unicode has a calendar character but it's in some distant code plane,
// use "keyboard" since it looks vaguely similar.
$page->setGlyph("\xE2\x8C\xA8");
$page->appendChild($view);
$page->setTabs(
array(
),
idx($data, 'tab'));
$response = new AphrontWebpageResponse();
return $response->setContent($page->render());
}
}

View file

@ -0,0 +1,15 @@
<?php
/**
* This file is automatically generated. Lint this module to rebuild it.
* @generated
*/
phutil_require_module('phabricator', 'aphront/response/webpage');
phutil_require_module('phabricator', 'applications/base/controller/base');
phutil_require_module('phutil', 'utils');
phutil_require_source('PhabricatorCalendarController.php');

View file

@ -0,0 +1,41 @@
<?php
/*
* Copyright 2011 Facebook, Inc.
*
* 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.
*/
class PhabricatorCalendarBrowseController
extends PhabricatorCalendarController {
public function processRequest() {
$request = $this->getRequest();
$user = $request->getUser();
$months = array();
for ($ii = 1; $ii <= 12; $ii++) {
$month_view = new AphrontCalendarMonthView($ii, 2011);
$month_view->setUser($user);
$months[] = '<div style="padding: 2em;">';
$months[] = $month_view;
$months[] = '</div>';
}
return $this->buildStandardPageResponse(
$months,
array(
'title' => 'Calendar',
));
}
}

View file

@ -0,0 +1,13 @@
<?php
/**
* This file is automatically generated. Lint this module to rebuild it.
* @generated
*/
phutil_require_module('phabricator', 'applications/calendar/controller/base');
phutil_require_module('phabricator', 'applications/calendar/view/month');
phutil_require_source('PhabricatorCalendarBrowseController.php');

View file

@ -0,0 +1,131 @@
<?php
/*
* Copyright 2011 Facebook, Inc.
*
* 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;
public function setUser(PhabricatorUser $user) {
$this->user = $user;
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()!");
}
$days = $this->getDatesInMonth();
require_celerity_resource('aphront-calendar-view-css');
$first = reset($days);
$empty = $first->format('w');
$markup = array();
for ($ii = 0; $ii < $empty; $ii++) {
$markup[] = null;
}
foreach ($days as $day) {
$markup[] =
'<div class="aphront-calendar-day-of-month">'.
$day->format('j').
'</div>';
}
$table = array();
$rows = array_chunk($markup, 7);
foreach ($rows as $row) {
$table[] = '<tr>';
while (count($row) < 7) {
$row[] = null;
}
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;
}
}

View file

@ -0,0 +1,13 @@
<?php
/**
* This file is automatically generated. Lint this module to rebuild it.
* @generated
*/
phutil_require_module('phabricator', 'infrastructure/celerity/api');
phutil_require_module('phabricator', 'view/base');
phutil_require_source('AphrontCalendarMonthView.php');

View file

@ -0,0 +1,41 @@
/**
* @provides aphront-calendar-view-css
*/
.aphront-calendar-view {
width: 100%;
border-collapse: collapse;
background: #fdfdfd;
border: 2px solid #003366;
}
tr.aphront-calendar-month-year-header th {
text-align: center;
font-weight: bold;
font-size: 14px;
padding: .5em;
color: white;
background: #003366;
}
tr.aphront-calendar-day-of-week-header th {
text-align: center;
font-size: 11px;
padding: .25em;
color: white;
background: #3366BB;
}
table.aphront-calendar-view td {
border: 1px solid #dfdfdf;
padding: .5em;
}
table.aphront-calendar-view td div {
min-height: 70px;
}
.aphront-calendar-day-of-month {
text-align: right;
color: #666666;
}