mirror of
https://we.phorge.it/source/phorge.git
synced 2024-12-18 19:40: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:
parent
e4c9914697
commit
e8dbdedbd4
5 changed files with 100 additions and 170 deletions
|
@ -5,9 +5,7 @@ final class AphrontFormDateControl extends AphrontFormControl {
|
|||
private $initialTime;
|
||||
private $zone;
|
||||
|
||||
private $valueDay;
|
||||
private $valueMonth;
|
||||
private $valueYear;
|
||||
private $valueDate;
|
||||
private $valueTime;
|
||||
private $allowNull;
|
||||
private $continueOnInvalidDate = false;
|
||||
|
@ -41,9 +39,7 @@ final class AphrontFormDateControl extends AphrontFormControl {
|
|||
}
|
||||
|
||||
public function readValueFromRequest(AphrontRequest $request) {
|
||||
$day = $request->getInt($this->getDayInputName());
|
||||
$month = $request->getInt($this->getMonthInputName());
|
||||
$year = $request->getInt($this->getYearInputName());
|
||||
$date = $request->getStr($this->getDateInputName());
|
||||
$time = $request->getStr($this->getTimeInputName());
|
||||
$enabled = $request->getBool($this->getCheckboxInputName());
|
||||
|
||||
|
@ -55,10 +51,8 @@ final class AphrontFormDateControl extends AphrontFormControl {
|
|||
|
||||
$err = $this->getError();
|
||||
|
||||
if ($day || $month || $year || $time) {
|
||||
$this->valueDay = $day;
|
||||
$this->valueMonth = $month;
|
||||
$this->valueYear = $year;
|
||||
if ($date || $time) {
|
||||
$this->valueDate = $date;
|
||||
$this->valueTime = $time;
|
||||
|
||||
// Assume invalid.
|
||||
|
@ -67,8 +61,8 @@ final class AphrontFormDateControl extends AphrontFormControl {
|
|||
$zone = $this->getTimezone();
|
||||
|
||||
try {
|
||||
$date = new DateTime("{$year}-{$month}-{$day} {$time}", $zone);
|
||||
$value = $date->format('U');
|
||||
$datetime = new DateTime("{$date} {$time}", $zone);
|
||||
$value = $datetime->format('U');
|
||||
} catch (Exception $ex) {
|
||||
$value = null;
|
||||
}
|
||||
|
@ -100,9 +94,7 @@ final class AphrontFormDateControl extends AphrontFormControl {
|
|||
public function setValue($epoch) {
|
||||
if ($epoch instanceof AphrontFormDateControlValue) {
|
||||
$this->continueOnInvalidDate = true;
|
||||
$this->valueYear = $epoch->getValueYear();
|
||||
$this->valueMonth = $epoch->getValueMonth();
|
||||
$this->valueDay = $epoch->getValueDay();
|
||||
$this->valueDate = $epoch->getValueDate();
|
||||
$this->valueTime = $epoch->getValueTime();
|
||||
$this->allowNull = $epoch->getOptional();
|
||||
$this->isDisabled = $epoch->isDisabled();
|
||||
|
@ -119,42 +111,18 @@ final class AphrontFormDateControl extends AphrontFormControl {
|
|||
$readable = $this->formatTime($epoch, 'Y!m!d!g:i A');
|
||||
$readable = explode('!', $readable, 4);
|
||||
|
||||
$this->valueYear = $readable[0];
|
||||
$this->valueMonth = $readable[1];
|
||||
$this->valueDay = $readable[2];
|
||||
$year = $readable[0];
|
||||
$month = $readable[1];
|
||||
$day = $readable[2];
|
||||
|
||||
$this->valueDate = $month.'/'.$day.'/'.$year;
|
||||
$this->valueTime = $readable[3];
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
private function getMinYear() {
|
||||
$cur_year = $this->formatTime(
|
||||
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 getDateInputValue() {
|
||||
return $this->valueDate;
|
||||
}
|
||||
|
||||
private function getTimeInputValue() {
|
||||
|
@ -168,18 +136,10 @@ final class AphrontFormDateControl extends AphrontFormControl {
|
|||
$fmt);
|
||||
}
|
||||
|
||||
private function getDayInputName() {
|
||||
private function getDateInputName() {
|
||||
return $this->getName().'_d';
|
||||
}
|
||||
|
||||
private function getMonthInputName() {
|
||||
return $this->getName().'_m';
|
||||
}
|
||||
|
||||
private function getYearInputName() {
|
||||
return $this->getName().'_y';
|
||||
}
|
||||
|
||||
private function getTimeInputName() {
|
||||
return $this->getName().'_t';
|
||||
}
|
||||
|
@ -202,27 +162,6 @@ final class AphrontFormDateControl extends AphrontFormControl {
|
|||
$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;
|
||||
if ($this->allowNull) {
|
||||
$checkbox = javelin_tag(
|
||||
|
@ -237,32 +176,24 @@ final class AphrontFormDateControl extends AphrontFormControl {
|
|||
));
|
||||
}
|
||||
|
||||
$years = range($this->getMinYear(), $this->getMaxYear());
|
||||
$years = array_fuse($years);
|
||||
|
||||
$days_sel = AphrontFormSelectControl::renderSelectTag(
|
||||
$this->getDayInputValue(),
|
||||
$days,
|
||||
$date_sel = javelin_tag(
|
||||
'input',
|
||||
array(
|
||||
'name' => $this->getDayInputName(),
|
||||
'sigil' => 'day-input',
|
||||
));
|
||||
'autocomplete' => 'off',
|
||||
'name' => $this->getDateInputName(),
|
||||
'sigil' => 'date-input',
|
||||
'value' => $this->getDateInputValue(),
|
||||
'type' => 'text',
|
||||
'class' => 'aphront-form-date-time-input',
|
||||
),
|
||||
'');
|
||||
|
||||
$months_sel = AphrontFormSelectControl::renderSelectTag(
|
||||
$this->getMonthInputValue(),
|
||||
$months,
|
||||
$date_div = javelin_tag(
|
||||
'div',
|
||||
array(
|
||||
'name' => $this->getMonthInputName(),
|
||||
'sigil' => 'month-input',
|
||||
));
|
||||
|
||||
$years_sel = AphrontFormSelectControl::renderSelectTag(
|
||||
$this->getYearInputValue(),
|
||||
$years,
|
||||
array(
|
||||
'name' => $this->getYearInputName(),
|
||||
'sigil' => 'year-input',
|
||||
));
|
||||
'class' => 'aphront-form-date-time-input-container',
|
||||
),
|
||||
$date_sel);
|
||||
|
||||
$cicon = id(new PHUIIconView())
|
||||
->setIconFont('fa-calendar');
|
||||
|
@ -329,9 +260,7 @@ final class AphrontFormDateControl extends AphrontFormControl {
|
|||
),
|
||||
array(
|
||||
$checkbox,
|
||||
$days_sel,
|
||||
$months_sel,
|
||||
$years_sel,
|
||||
$date_div,
|
||||
$cal_icon,
|
||||
$time_div,
|
||||
));
|
||||
|
|
|
@ -2,9 +2,7 @@
|
|||
|
||||
final class AphrontFormDateControlValue extends Phobject {
|
||||
|
||||
private $valueDay;
|
||||
private $valueMonth;
|
||||
private $valueYear;
|
||||
private $valueDate;
|
||||
private $valueTime;
|
||||
private $valueEnabled;
|
||||
|
||||
|
@ -12,16 +10,8 @@ final class AphrontFormDateControlValue extends Phobject {
|
|||
private $zone;
|
||||
private $optional;
|
||||
|
||||
public function getValueDay() {
|
||||
return $this->valueDay;
|
||||
}
|
||||
|
||||
public function getValueMonth() {
|
||||
return $this->valueMonth;
|
||||
}
|
||||
|
||||
public function getValueYear() {
|
||||
return $this->valueYear;
|
||||
public function getValueDate() {
|
||||
return $this->valueDate;
|
||||
}
|
||||
|
||||
public function getValueTime() {
|
||||
|
@ -36,15 +26,7 @@ final class AphrontFormDateControlValue extends Phobject {
|
|||
}
|
||||
|
||||
public function isEmpty() {
|
||||
if ($this->valueDay) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if ($this->valueMonth) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if ($this->valueYear) {
|
||||
if ($this->valueDate) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -83,9 +65,7 @@ final class AphrontFormDateControlValue extends Phobject {
|
|||
|
||||
$value = new AphrontFormDateControlValue();
|
||||
$value->viewer = $viewer;
|
||||
$value->valueYear = $year;
|
||||
$value->valueMonth = $month;
|
||||
$value->valueDay = $day;
|
||||
$value->valueDate = $month.'/'.$day.'/'.$year;
|
||||
$value->valueTime = coalesce($time, '12:00 AM');
|
||||
$value->valueEnabled = $enabled;
|
||||
|
||||
|
@ -95,10 +75,7 @@ final class AphrontFormDateControlValue extends Phobject {
|
|||
public static function newFromRequest(AphrontRequest $request, $key) {
|
||||
$value = new AphrontFormDateControlValue();
|
||||
$value->viewer = $request->getViewer();
|
||||
|
||||
$value->valueDay = $request->getInt($key.'_d');
|
||||
$value->valueMonth = $request->getInt($key.'_m');
|
||||
$value->valueYear = $request->getInt($key.'_y');
|
||||
$value->valueDate = $request->getStr($key.'_d');
|
||||
$value->valueTime = $request->getStr($key.'_t');
|
||||
$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 = explode('!', $readable, 4);
|
||||
|
||||
$value->valueYear = $readable[0];
|
||||
$value->valueMonth = $readable[1];
|
||||
$value->valueDay = $readable[2];
|
||||
$year = $readable[0];
|
||||
$month = $readable[1];
|
||||
$day = $readable[2];
|
||||
|
||||
$value->valueDate = $month.'/'.$day.'/'.$year;
|
||||
$value->valueTime = $readable[3];
|
||||
|
||||
|
||||
return $value;
|
||||
}
|
||||
|
||||
|
@ -125,9 +105,7 @@ final class AphrontFormDateControlValue extends Phobject {
|
|||
$value = new AphrontFormDateControlValue();
|
||||
$value->viewer = $viewer;
|
||||
|
||||
$value->valueYear = idx($dictionary, 'y');
|
||||
$value->valueMonth = idx($dictionary, 'm');
|
||||
$value->valueDay = idx($dictionary, 'd');
|
||||
$value->valueDate = idx($dictionary, 'd');
|
||||
$value->valueTime = idx($dictionary, 't');
|
||||
$value->valueEnabled = idx($dictionary, 'e');
|
||||
|
||||
|
@ -149,9 +127,7 @@ final class AphrontFormDateControlValue extends Phobject {
|
|||
|
||||
public function getDictionary() {
|
||||
return array(
|
||||
'y' => $this->valueYear,
|
||||
'm' => $this->valueMonth,
|
||||
'd' => $this->valueDay,
|
||||
'd' => $this->valueDate,
|
||||
't' => $this->valueTime,
|
||||
'e' => $this->valueEnabled,
|
||||
);
|
||||
|
@ -176,9 +152,7 @@ final class AphrontFormDateControlValue extends Phobject {
|
|||
return null;
|
||||
}
|
||||
|
||||
$year = $this->valueYear;
|
||||
$month = $this->valueMonth;
|
||||
$day = $this->valueDay;
|
||||
$date = $this->valueDate;
|
||||
$time = $this->valueTime;
|
||||
$zone = $this->getTimezone();
|
||||
|
||||
|
@ -203,8 +177,8 @@ final class AphrontFormDateControlValue extends Phobject {
|
|||
}
|
||||
|
||||
try {
|
||||
$date = new DateTime("{$year}-{$month}-{$day} {$time}", $zone);
|
||||
$value = $date->format('U');
|
||||
$datetime = new DateTime("{$date} {$time}", $zone);
|
||||
$value = $datetime->format('U');
|
||||
} catch (Exception $ex) {
|
||||
$value = null;
|
||||
}
|
||||
|
|
|
@ -90,10 +90,7 @@ final class PHUICalendarDayView extends AphrontView {
|
|||
}
|
||||
|
||||
$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) {
|
||||
if ($event->getIsAllDay()) {
|
||||
|
|
|
@ -150,8 +150,11 @@ final class PHUICalendarListView extends AphrontTagView {
|
|||
$this->getUser(),
|
||||
$event->getEpochEnd()));
|
||||
|
||||
$start_date = $start->getDateTime()->format('m d Y');
|
||||
$end_date = $end->getDateTime()->format('m d Y');
|
||||
|
||||
if ($event->getIsAllDay()) {
|
||||
if ($start->getValueDay() == $end->getValueDay()) {
|
||||
if ($start_date == $end_date) {
|
||||
$tip = pht('All day');
|
||||
} else {
|
||||
$tip = pht(
|
||||
|
@ -160,9 +163,7 @@ final class PHUICalendarListView extends AphrontTagView {
|
|||
$end->getValueAsFormat('M j, Y'));
|
||||
}
|
||||
} else {
|
||||
if ($start->getValueDay() == $end->getValueDay() &&
|
||||
$start->getValueMonth() == $end->getValueMonth() &&
|
||||
$start->getValueYear() == $end->getValueYear()) {
|
||||
if ($start->getValueDate() == $end->getValueDate()) {
|
||||
$tip = pht(
|
||||
'%s - %s',
|
||||
$start->getValueAsFormat('g:i A'),
|
||||
|
|
|
@ -78,25 +78,23 @@ JX.behavior('fancy-datepicker', function() {
|
|||
|
||||
var get_inputs = function() {
|
||||
return {
|
||||
y: JX.DOM.find(root, 'select', 'year-input'),
|
||||
m: JX.DOM.find(root, 'select', 'month-input'),
|
||||
d: JX.DOM.find(root, 'select', 'day-input'),
|
||||
d: JX.DOM.find(root, 'input', 'date-input'),
|
||||
t: JX.DOM.find(root, 'input', 'time-input')
|
||||
};
|
||||
};
|
||||
|
||||
var read_date = function() {
|
||||
var i = get_inputs();
|
||||
value_y = +i.y.value;
|
||||
value_m = +i.m.value;
|
||||
value_d = +i.d.value;
|
||||
var date = i.d.value;
|
||||
var parts = date.split('/');
|
||||
value_y = +parts[2];
|
||||
value_m = +parts[0];
|
||||
value_d = +parts[1];
|
||||
};
|
||||
|
||||
var write_date = function() {
|
||||
var i = get_inputs();
|
||||
i.y.value = value_y;
|
||||
i.m.value = value_m;
|
||||
i.d.value = value_d;
|
||||
i.d.value = value_m + '/' + value_d + '/' + value_y;
|
||||
};
|
||||
|
||||
var render = function() {
|
||||
|
@ -133,9 +131,12 @@ JX.behavior('fancy-datepicker', function() {
|
|||
return JX.$N('td', {meta: {value: value}, className: class_name}, label);
|
||||
};
|
||||
|
||||
|
||||
// Render the top bar which allows you to pick a month and year.
|
||||
var render_month = function() {
|
||||
var valid_date = getValidDate();
|
||||
var month = valid_date.getMonth();
|
||||
var year = valid_date.getYear() + 1900;
|
||||
|
||||
var months = [
|
||||
'January',
|
||||
'February',
|
||||
|
@ -152,7 +153,7 @@ JX.behavior('fancy-datepicker', function() {
|
|||
|
||||
var buttons = [
|
||||
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')];
|
||||
|
||||
return JX.$N(
|
||||
|
@ -161,9 +162,21 @@ JX.behavior('fancy-datepicker', function() {
|
|||
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.
|
||||
var render_day = function() {
|
||||
var today = new Date();
|
||||
var valid_date = getValidDate();
|
||||
|
||||
var weeks = [];
|
||||
|
||||
// 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
|
||||
// while we use 1-based month indexes, so we have to adjust for that.
|
||||
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--) {
|
||||
days.push(cell('', null, false, 'day-placeholder'));
|
||||
}
|
||||
|
||||
var today = new Date();
|
||||
|
||||
for (ii = 1; ii <= 31; ii++) {
|
||||
var date = new Date(value_y, value_m - 1, ii);
|
||||
if (date.getMonth() != (value_m - 1)) {
|
||||
var date = new Date(
|
||||
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.
|
||||
break;
|
||||
}
|
||||
|
@ -206,7 +224,11 @@ JX.behavior('fancy-datepicker', function() {
|
|||
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.
|
||||
|
@ -263,4 +285,11 @@ JX.behavior('fancy-datepicker', function() {
|
|||
render();
|
||||
});
|
||||
|
||||
JX.Stratcom.listen('click', null, function(e){
|
||||
if (e.getNode('phabricator-datepicker')) {
|
||||
return;
|
||||
}
|
||||
onclose();
|
||||
});
|
||||
|
||||
});
|
||||
|
|
Loading…
Reference in a new issue