1
0
Fork 0
mirror of https://we.phorge.it/source/phorge.git synced 2024-12-20 04:20:55 +01:00

Convert date control dropdowns to an input for date

Summary: Ref T8060, Convert date control dropdowns to an input for date

Test Plan: Create new Calendar event, use US time format to enter a date or use datepicker, confirm dates are interpreted correctly.

Reviewers: #blessed_reviewers, epriestley

Reviewed By: #blessed_reviewers, epriestley

Subscribers: Korvin, epriestley

Maniphest Tasks: T8060

Differential Revision: https://secure.phabricator.com/D13010
This commit is contained in:
lkassianik 2015-05-25 14:02:33 -07:00
parent e4c9914697
commit e8dbdedbd4
5 changed files with 100 additions and 170 deletions

View file

@ -5,9 +5,7 @@ final class AphrontFormDateControl extends AphrontFormControl {
private $initialTime; private $initialTime;
private $zone; private $zone;
private $valueDay; private $valueDate;
private $valueMonth;
private $valueYear;
private $valueTime; private $valueTime;
private $allowNull; private $allowNull;
private $continueOnInvalidDate = false; private $continueOnInvalidDate = false;
@ -41,9 +39,7 @@ final class AphrontFormDateControl extends AphrontFormControl {
} }
public function readValueFromRequest(AphrontRequest $request) { public function readValueFromRequest(AphrontRequest $request) {
$day = $request->getInt($this->getDayInputName()); $date = $request->getStr($this->getDateInputName());
$month = $request->getInt($this->getMonthInputName());
$year = $request->getInt($this->getYearInputName());
$time = $request->getStr($this->getTimeInputName()); $time = $request->getStr($this->getTimeInputName());
$enabled = $request->getBool($this->getCheckboxInputName()); $enabled = $request->getBool($this->getCheckboxInputName());
@ -55,10 +51,8 @@ final class AphrontFormDateControl extends AphrontFormControl {
$err = $this->getError(); $err = $this->getError();
if ($day || $month || $year || $time) { if ($date || $time) {
$this->valueDay = $day; $this->valueDate = $date;
$this->valueMonth = $month;
$this->valueYear = $year;
$this->valueTime = $time; $this->valueTime = $time;
// Assume invalid. // Assume invalid.
@ -67,8 +61,8 @@ final class AphrontFormDateControl extends AphrontFormControl {
$zone = $this->getTimezone(); $zone = $this->getTimezone();
try { try {
$date = new DateTime("{$year}-{$month}-{$day} {$time}", $zone); $datetime = new DateTime("{$date} {$time}", $zone);
$value = $date->format('U'); $value = $datetime->format('U');
} catch (Exception $ex) { } catch (Exception $ex) {
$value = null; $value = null;
} }
@ -100,9 +94,7 @@ final class AphrontFormDateControl extends AphrontFormControl {
public function setValue($epoch) { public function setValue($epoch) {
if ($epoch instanceof AphrontFormDateControlValue) { if ($epoch instanceof AphrontFormDateControlValue) {
$this->continueOnInvalidDate = true; $this->continueOnInvalidDate = true;
$this->valueYear = $epoch->getValueYear(); $this->valueDate = $epoch->getValueDate();
$this->valueMonth = $epoch->getValueMonth();
$this->valueDay = $epoch->getValueDay();
$this->valueTime = $epoch->getValueTime(); $this->valueTime = $epoch->getValueTime();
$this->allowNull = $epoch->getOptional(); $this->allowNull = $epoch->getOptional();
$this->isDisabled = $epoch->isDisabled(); $this->isDisabled = $epoch->isDisabled();
@ -119,42 +111,18 @@ final class AphrontFormDateControl extends AphrontFormControl {
$readable = $this->formatTime($epoch, 'Y!m!d!g:i A'); $readable = $this->formatTime($epoch, 'Y!m!d!g:i A');
$readable = explode('!', $readable, 4); $readable = explode('!', $readable, 4);
$this->valueYear = $readable[0]; $year = $readable[0];
$this->valueMonth = $readable[1]; $month = $readable[1];
$this->valueDay = $readable[2]; $day = $readable[2];
$this->valueDate = $month.'/'.$day.'/'.$year;
$this->valueTime = $readable[3]; $this->valueTime = $readable[3];
return $result; return $result;
} }
private function getMinYear() { private function getDateInputValue() {
$cur_year = $this->formatTime( return $this->valueDate;
time(),
'Y');
$val_year = $this->getYearInputValue();
return min($cur_year, $val_year) - 3;
}
private function getMaxYear() {
$cur_year = $this->formatTime(
time(),
'Y');
$val_year = $this->getYearInputValue();
return max($cur_year, $val_year) + 3;
}
private function getDayInputValue() {
return $this->valueDay;
}
private function getMonthInputValue() {
return $this->valueMonth;
}
private function getYearInputValue() {
return $this->valueYear;
} }
private function getTimeInputValue() { private function getTimeInputValue() {
@ -168,18 +136,10 @@ final class AphrontFormDateControl extends AphrontFormControl {
$fmt); $fmt);
} }
private function getDayInputName() { private function getDateInputName() {
return $this->getName().'_d'; return $this->getName().'_d';
} }
private function getMonthInputName() {
return $this->getName().'_m';
}
private function getYearInputName() {
return $this->getName().'_y';
}
private function getTimeInputName() { private function getTimeInputName() {
return $this->getName().'_t'; return $this->getName().'_t';
} }
@ -202,27 +162,6 @@ final class AphrontFormDateControl extends AphrontFormControl {
$disabled = 'disabled'; $disabled = 'disabled';
} }
$min_year = $this->getMinYear();
$max_year = $this->getMaxYear();
$days = range(1, 31);
$days = array_fuse($days);
$months = array(
1 => pht('Jan'),
2 => pht('Feb'),
3 => pht('Mar'),
4 => pht('Apr'),
5 => pht('May'),
6 => pht('Jun'),
7 => pht('Jul'),
8 => pht('Aug'),
9 => pht('Sep'),
10 => pht('Oct'),
11 => pht('Nov'),
12 => pht('Dec'),
);
$checkbox = null; $checkbox = null;
if ($this->allowNull) { if ($this->allowNull) {
$checkbox = javelin_tag( $checkbox = javelin_tag(
@ -237,32 +176,24 @@ final class AphrontFormDateControl extends AphrontFormControl {
)); ));
} }
$years = range($this->getMinYear(), $this->getMaxYear()); $date_sel = javelin_tag(
$years = array_fuse($years); 'input',
$days_sel = AphrontFormSelectControl::renderSelectTag(
$this->getDayInputValue(),
$days,
array( array(
'name' => $this->getDayInputName(), 'autocomplete' => 'off',
'sigil' => 'day-input', 'name' => $this->getDateInputName(),
)); 'sigil' => 'date-input',
'value' => $this->getDateInputValue(),
'type' => 'text',
'class' => 'aphront-form-date-time-input',
),
'');
$months_sel = AphrontFormSelectControl::renderSelectTag( $date_div = javelin_tag(
$this->getMonthInputValue(), 'div',
$months,
array( array(
'name' => $this->getMonthInputName(), 'class' => 'aphront-form-date-time-input-container',
'sigil' => 'month-input', ),
)); $date_sel);
$years_sel = AphrontFormSelectControl::renderSelectTag(
$this->getYearInputValue(),
$years,
array(
'name' => $this->getYearInputName(),
'sigil' => 'year-input',
));
$cicon = id(new PHUIIconView()) $cicon = id(new PHUIIconView())
->setIconFont('fa-calendar'); ->setIconFont('fa-calendar');
@ -329,9 +260,7 @@ final class AphrontFormDateControl extends AphrontFormControl {
), ),
array( array(
$checkbox, $checkbox,
$days_sel, $date_div,
$months_sel,
$years_sel,
$cal_icon, $cal_icon,
$time_div, $time_div,
)); ));

View file

@ -2,9 +2,7 @@
final class AphrontFormDateControlValue extends Phobject { final class AphrontFormDateControlValue extends Phobject {
private $valueDay; private $valueDate;
private $valueMonth;
private $valueYear;
private $valueTime; private $valueTime;
private $valueEnabled; private $valueEnabled;
@ -12,16 +10,8 @@ final class AphrontFormDateControlValue extends Phobject {
private $zone; private $zone;
private $optional; private $optional;
public function getValueDay() { public function getValueDate() {
return $this->valueDay; return $this->valueDate;
}
public function getValueMonth() {
return $this->valueMonth;
}
public function getValueYear() {
return $this->valueYear;
} }
public function getValueTime() { public function getValueTime() {
@ -36,15 +26,7 @@ final class AphrontFormDateControlValue extends Phobject {
} }
public function isEmpty() { public function isEmpty() {
if ($this->valueDay) { if ($this->valueDate) {
return false;
}
if ($this->valueMonth) {
return false;
}
if ($this->valueYear) {
return false; return false;
} }
@ -83,9 +65,7 @@ final class AphrontFormDateControlValue extends Phobject {
$value = new AphrontFormDateControlValue(); $value = new AphrontFormDateControlValue();
$value->viewer = $viewer; $value->viewer = $viewer;
$value->valueYear = $year; $value->valueDate = $month.'/'.$day.'/'.$year;
$value->valueMonth = $month;
$value->valueDay = $day;
$value->valueTime = coalesce($time, '12:00 AM'); $value->valueTime = coalesce($time, '12:00 AM');
$value->valueEnabled = $enabled; $value->valueEnabled = $enabled;
@ -95,10 +75,7 @@ final class AphrontFormDateControlValue extends Phobject {
public static function newFromRequest(AphrontRequest $request, $key) { public static function newFromRequest(AphrontRequest $request, $key) {
$value = new AphrontFormDateControlValue(); $value = new AphrontFormDateControlValue();
$value->viewer = $request->getViewer(); $value->viewer = $request->getViewer();
$value->valueDate = $request->getStr($key.'_d');
$value->valueDay = $request->getInt($key.'_d');
$value->valueMonth = $request->getInt($key.'_m');
$value->valueYear = $request->getInt($key.'_y');
$value->valueTime = $request->getStr($key.'_t'); $value->valueTime = $request->getStr($key.'_t');
$value->valueEnabled = $request->getStr($key.'_e'); $value->valueEnabled = $request->getStr($key.'_e');
@ -111,11 +88,14 @@ final class AphrontFormDateControlValue extends Phobject {
$readable = $value->formatTime($epoch, 'Y!m!d!g:i A'); $readable = $value->formatTime($epoch, 'Y!m!d!g:i A');
$readable = explode('!', $readable, 4); $readable = explode('!', $readable, 4);
$value->valueYear = $readable[0]; $year = $readable[0];
$value->valueMonth = $readable[1]; $month = $readable[1];
$value->valueDay = $readable[2]; $day = $readable[2];
$value->valueDate = $month.'/'.$day.'/'.$year;
$value->valueTime = $readable[3]; $value->valueTime = $readable[3];
return $value; return $value;
} }
@ -125,9 +105,7 @@ final class AphrontFormDateControlValue extends Phobject {
$value = new AphrontFormDateControlValue(); $value = new AphrontFormDateControlValue();
$value->viewer = $viewer; $value->viewer = $viewer;
$value->valueYear = idx($dictionary, 'y'); $value->valueDate = idx($dictionary, 'd');
$value->valueMonth = idx($dictionary, 'm');
$value->valueDay = idx($dictionary, 'd');
$value->valueTime = idx($dictionary, 't'); $value->valueTime = idx($dictionary, 't');
$value->valueEnabled = idx($dictionary, 'e'); $value->valueEnabled = idx($dictionary, 'e');
@ -149,9 +127,7 @@ final class AphrontFormDateControlValue extends Phobject {
public function getDictionary() { public function getDictionary() {
return array( return array(
'y' => $this->valueYear, 'd' => $this->valueDate,
'm' => $this->valueMonth,
'd' => $this->valueDay,
't' => $this->valueTime, 't' => $this->valueTime,
'e' => $this->valueEnabled, 'e' => $this->valueEnabled,
); );
@ -176,9 +152,7 @@ final class AphrontFormDateControlValue extends Phobject {
return null; return null;
} }
$year = $this->valueYear; $date = $this->valueDate;
$month = $this->valueMonth;
$day = $this->valueDay;
$time = $this->valueTime; $time = $this->valueTime;
$zone = $this->getTimezone(); $zone = $this->getTimezone();
@ -203,8 +177,8 @@ final class AphrontFormDateControlValue extends Phobject {
} }
try { try {
$date = new DateTime("{$year}-{$month}-{$day} {$time}", $zone); $datetime = new DateTime("{$date} {$time}", $zone);
$value = $date->format('U'); $value = $datetime->format('U');
} catch (Exception $ex) { } catch (Exception $ex) {
$value = null; $value = null;
} }

View file

@ -90,10 +90,7 @@ final class PHUICalendarDayView extends AphrontView {
} }
$this->events = msort($this->events, 'getEpochStart'); $this->events = msort($this->events, 'getEpochStart');
if (!$this->events) {
$first_event_hour = $this->getDateTime()->setTime(8, 0, 0); $first_event_hour = $this->getDateTime()->setTime(8, 0, 0);
}
foreach ($this->events as $event) { foreach ($this->events as $event) {
if ($event->getIsAllDay()) { if ($event->getIsAllDay()) {

View file

@ -150,8 +150,11 @@ final class PHUICalendarListView extends AphrontTagView {
$this->getUser(), $this->getUser(),
$event->getEpochEnd())); $event->getEpochEnd()));
$start_date = $start->getDateTime()->format('m d Y');
$end_date = $end->getDateTime()->format('m d Y');
if ($event->getIsAllDay()) { if ($event->getIsAllDay()) {
if ($start->getValueDay() == $end->getValueDay()) { if ($start_date == $end_date) {
$tip = pht('All day'); $tip = pht('All day');
} else { } else {
$tip = pht( $tip = pht(
@ -160,9 +163,7 @@ final class PHUICalendarListView extends AphrontTagView {
$end->getValueAsFormat('M j, Y')); $end->getValueAsFormat('M j, Y'));
} }
} else { } else {
if ($start->getValueDay() == $end->getValueDay() && if ($start->getValueDate() == $end->getValueDate()) {
$start->getValueMonth() == $end->getValueMonth() &&
$start->getValueYear() == $end->getValueYear()) {
$tip = pht( $tip = pht(
'%s - %s', '%s - %s',
$start->getValueAsFormat('g:i A'), $start->getValueAsFormat('g:i A'),

View file

@ -78,25 +78,23 @@ JX.behavior('fancy-datepicker', function() {
var get_inputs = function() { var get_inputs = function() {
return { return {
y: JX.DOM.find(root, 'select', 'year-input'), d: JX.DOM.find(root, 'input', 'date-input'),
m: JX.DOM.find(root, 'select', 'month-input'),
d: JX.DOM.find(root, 'select', 'day-input'),
t: JX.DOM.find(root, 'input', 'time-input') t: JX.DOM.find(root, 'input', 'time-input')
}; };
}; };
var read_date = function() { var read_date = function() {
var i = get_inputs(); var i = get_inputs();
value_y = +i.y.value; var date = i.d.value;
value_m = +i.m.value; var parts = date.split('/');
value_d = +i.d.value; value_y = +parts[2];
value_m = +parts[0];
value_d = +parts[1];
}; };
var write_date = function() { var write_date = function() {
var i = get_inputs(); var i = get_inputs();
i.y.value = value_y; i.d.value = value_m + '/' + value_d + '/' + value_y;
i.m.value = value_m;
i.d.value = value_d;
}; };
var render = function() { var render = function() {
@ -133,9 +131,12 @@ JX.behavior('fancy-datepicker', function() {
return JX.$N('td', {meta: {value: value}, className: class_name}, label); return JX.$N('td', {meta: {value: value}, className: class_name}, label);
}; };
// Render the top bar which allows you to pick a month and year. // Render the top bar which allows you to pick a month and year.
var render_month = function() { var render_month = function() {
var valid_date = getValidDate();
var month = valid_date.getMonth();
var year = valid_date.getYear() + 1900;
var months = [ var months = [
'January', 'January',
'February', 'February',
@ -152,7 +153,7 @@ JX.behavior('fancy-datepicker', function() {
var buttons = [ var buttons = [
cell('\u25C0', 'm:-1', false, 'lrbutton'), cell('\u25C0', 'm:-1', false, 'lrbutton'),
cell(months[value_m - 1] + ' ' + value_y, null), cell(months[month] + ' ' + year, null),
cell('\u25B6', 'm:1', false, 'lrbutton')]; cell('\u25B6', 'm:1', false, 'lrbutton')];
return JX.$N( return JX.$N(
@ -161,9 +162,21 @@ JX.behavior('fancy-datepicker', function() {
JX.$N('tr', {}, buttons)); JX.$N('tr', {}, buttons));
}; };
function getValidDate() {
var written_date = new Date(value_y, value_m-1, value_d);
if (isNaN(written_date.getTime())) {
return new Date();
} else {
return written_date;
}
}
// Render the day-of-week and calendar views. // Render the day-of-week and calendar views.
var render_day = function() { var render_day = function() {
var today = new Date();
var valid_date = getValidDate();
var weeks = []; var weeks = [];
// First, render the weekday names. // First, render the weekday names.
@ -179,16 +192,21 @@ JX.behavior('fancy-datepicker', function() {
// Render the calendar itself. NOTE: Javascript uses 0-based month indexes // Render the calendar itself. NOTE: Javascript uses 0-based month indexes
// while we use 1-based month indexes, so we have to adjust for that. // while we use 1-based month indexes, so we have to adjust for that.
var days = []; var days = [];
var start = new Date(value_y, value_m - 1, 1).getDay(); var start = new Date(
valid_date.getYear() + 1900,
valid_date.getMonth(),
1).getDay();
while (start--) { while (start--) {
days.push(cell('', null, false, 'day-placeholder')); days.push(cell('', null, false, 'day-placeholder'));
} }
var today = new Date();
for (ii = 1; ii <= 31; ii++) { for (ii = 1; ii <= 31; ii++) {
var date = new Date(value_y, value_m - 1, ii); var date = new Date(
if (date.getMonth() != (value_m - 1)) { valid_date.getYear() + 1900,
valid_date.getMonth(),
ii);
if (date.getMonth() != (valid_date.getMonth())) {
// We've spilled over into the next month, so stop rendering. // We've spilled over into the next month, so stop rendering.
break; break;
} }
@ -206,7 +224,11 @@ JX.behavior('fancy-datepicker', function() {
classes.push('weekend'); classes.push('weekend');
} }
days.push(cell(ii, 'd:'+ii, value_d == ii, classes.join(' '))); days.push(cell(
ii,
'd:'+ii,
valid_date.getDate() == ii,
classes.join(' ')));
} }
// Slice the days into weeks. // Slice the days into weeks.
@ -263,4 +285,11 @@ JX.behavior('fancy-datepicker', function() {
render(); render();
}); });
JX.Stratcom.listen('click', null, function(e){
if (e.getNode('phabricator-datepicker')) {
return;
}
onclose();
});
}); });