Page MenuHomePhabricator

D12673.diff
No OneTemporary

D12673.diff

diff --git a/resources/celerity/map.php b/resources/celerity/map.php
--- a/resources/celerity/map.php
+++ b/resources/celerity/map.php
@@ -7,7 +7,7 @@
*/
return array(
'names' => array(
- 'core.pkg.css' => 'd445f9b8',
+ 'core.pkg.css' => 'ca3f6a60',
'core.pkg.js' => '3331b919',
'darkconsole.pkg.js' => 'e7393ebb',
'differential.pkg.css' => '0a253fbe',
@@ -132,7 +132,7 @@
'rsrc/css/phui/phui-document.css' => '94d5dcd8',
'rsrc/css/phui/phui-feed-story.css' => 'c9f3a0b5',
'rsrc/css/phui/phui-fontkit.css' => 'dd8ddf27',
- 'rsrc/css/phui/phui-form-view.css' => 'b147d2ed',
+ 'rsrc/css/phui/phui-form-view.css' => '17eace76',
'rsrc/css/phui/phui-form.css' => 'f535f938',
'rsrc/css/phui/phui-header-view.css' => 'da4586b1',
'rsrc/css/phui/phui-icon.css' => 'bc766998',
@@ -463,7 +463,7 @@
'rsrc/js/core/behavior-device.js' => 'a205cf28',
'rsrc/js/core/behavior-drag-and-drop-textarea.js' => '6d49590e',
'rsrc/js/core/behavior-error-log.js' => '6882e80a',
- 'rsrc/js/core/behavior-fancy-datepicker.js' => 'c51ae228',
+ 'rsrc/js/core/behavior-fancy-datepicker.js' => '5c0f680f',
'rsrc/js/core/behavior-file-tree.js' => '88236f00',
'rsrc/js/core/behavior-form.js' => '5c54cbf3',
'rsrc/js/core/behavior-gesture.js' => '3ab51e2c',
@@ -590,7 +590,7 @@
'javelin-behavior-doorkeeper-tag' => 'e5822781',
'javelin-behavior-durable-column' => '657c2b50',
'javelin-behavior-error-log' => '6882e80a',
- 'javelin-behavior-fancy-datepicker' => 'c51ae228',
+ 'javelin-behavior-fancy-datepicker' => '5c0f680f',
'javelin-behavior-global-drag-and-drop' => 'c203e6ee',
'javelin-behavior-herald-rule-editor' => '7ebaeed3',
'javelin-behavior-high-security-warning' => 'a464fe03',
@@ -789,7 +789,7 @@
'phui-font-icon-base-css' => '3dad2ae3',
'phui-fontkit-css' => 'dd8ddf27',
'phui-form-css' => 'f535f938',
- 'phui-form-view-css' => 'b147d2ed',
+ 'phui-form-view-css' => '17eace76',
'phui-header-view-css' => 'da4586b1',
'phui-icon-view-css' => 'bc766998',
'phui-image-mask-css' => '5a8b09c8',
@@ -1215,6 +1215,13 @@
'javelin-uri',
'javelin-routable',
),
+ '5c0f680f' => array(
+ 'javelin-behavior',
+ 'javelin-util',
+ 'javelin-dom',
+ 'javelin-stratcom',
+ 'javelin-vector',
+ ),
'5c54cbf3' => array(
'javelin-behavior',
'javelin-stratcom',
@@ -1768,13 +1775,6 @@
'javelin-mask',
'phabricator-drag-and-drop-file-upload',
),
- 'c51ae228' => array(
- 'javelin-behavior',
- 'javelin-util',
- 'javelin-dom',
- 'javelin-stratcom',
- 'javelin-vector',
- ),
'c90a04fc' => array(
'javelin-dom',
'javelin-dynval',
diff --git a/src/applications/calendar/query/PhabricatorCalendarEventSearchEngine.php b/src/applications/calendar/query/PhabricatorCalendarEventSearchEngine.php
--- a/src/applications/calendar/query/PhabricatorCalendarEventSearchEngine.php
+++ b/src/applications/calendar/query/PhabricatorCalendarEventSearchEngine.php
@@ -53,16 +53,8 @@
$query = id(new PhabricatorCalendarEventQuery());
$viewer = $this->requireViewer();
- $min_range = null;
- $max_range = null;
-
- if ($saved->getParameter('rangeStart')) {
- $min_range = $saved->getParameter('rangeStart');
- }
-
- if ($saved->getParameter('rangeEnd')) {
- $max_range = $saved->getParameter('rangeEnd');
- }
+ $min_range = $this->getDateFrom($saved)->getEpoch();
+ $max_range = $this->getDateTo($saved)->getEpoch();
if ($saved->getParameter('display') == 'month') {
list($start_month, $start_year) = $this->getDisplayMonthAndYear($saved);
@@ -130,8 +122,31 @@
AphrontFormView $form,
PhabricatorSavedQuery $saved) {
- $range_start = $saved->getParameter('rangeStart');
- $range_end = $saved->getParameter('rangeEnd');
+ $range_start = $this->getDateFrom($saved);
+ $e_start = null;
+
+ $range_end = $this->getDateTo($saved);
+ $e_end = null;
+
+ if (!$range_start->isValid()) {
+ $this->addError(pht('Start date is not valid.'));
+ $e_start = pht('Invalid');
+ }
+
+ if (!$range_end->isValid()) {
+ $this->addError(pht('End date is not valid.'));
+ $e_end = pht('Invalid');
+ }
+
+ $start_epoch = $range_start->getEpoch();
+ $end_epoch = $range_end->getEpoch();
+
+ if ($start_epoch && $end_epoch && ($start_epoch > $end_epoch)) {
+ $this->addError(pht('End date must be after start date.'));
+ $e_start = pht('Invalid');
+ $e_end = pht('Invalid');
+ }
+
$upcoming = $saved->getParameter('upcoming');
$is_cancelled = $saved->getParameter('isCancelled', 'active');
$display = $saved->getParameter('display', 'month');
@@ -167,14 +182,14 @@
->setLabel(pht('Occurs After'))
->setUser($this->requireViewer())
->setName('rangeStart')
- ->setAllowNull(true)
+ ->setError($e_start)
->setValue($range_start))
->appendChild(
id(new AphrontFormDateControl())
->setLabel(pht('Occurs Before'))
->setUser($this->requireViewer())
->setName('rangeEnd')
- ->setAllowNull(true)
+ ->setError($e_end)
->setValue($range_end))
->appendChild(
id(new AphrontFormCheckboxControl())
@@ -391,9 +406,9 @@
$start_year = $this->calendarYear;
$start_month = $this->calendarMonth;
} else {
- $epoch = $query->getParameter('rangeStart');
+ $epoch = $this->getDateFrom($query)->getEpoch();
if (!$epoch) {
- $epoch = $query->getParameter('rangeEnd');
+ $epoch = $this->getDateTo($query)->getEpoch();
if (!$epoch) {
$epoch = time();
}
@@ -431,4 +446,30 @@
return $saved->getParameter('limit', 1000);
}
+ private function getDateFrom(PhabricatorSavedQuery $saved) {
+ return $this->getDate($saved, 'rangeStart');
+ }
+
+ private function getDateTo(PhabricatorSavedQuery $saved) {
+ return $this->getDate($saved, 'rangeEnd');
+ }
+
+ private function getDate(PhabricatorSavedQuery $saved, $key) {
+ $viewer = $this->requireViewer();
+
+ $wild = $saved->getParameter($key);
+ if ($wild) {
+ $value = AphrontFormDateControlValue::newFromWild($viewer, $wild);
+ } else {
+ $value = AphrontFormDateControlValue::newFromEpoch(
+ $viewer,
+ PhabricatorTime::getNow());
+ $value->setEnabled(false);
+ }
+
+ $value->setOptional(true);
+
+ return $value;
+ }
+
}
diff --git a/src/applications/search/engine/PhabricatorApplicationSearchEngine.php b/src/applications/search/engine/PhabricatorApplicationSearchEngine.php
--- a/src/applications/search/engine/PhabricatorApplicationSearchEngine.php
+++ b/src/applications/search/engine/PhabricatorApplicationSearchEngine.php
@@ -566,11 +566,13 @@
AphrontRequest $request,
$key) {
- return id(new AphrontFormDateControl())
- ->setUser($this->requireViewer())
- ->setName($key)
- ->setAllowNull(true)
- ->readValueFromRequest($request);
+ $value = AphrontFormDateControlValue::newFromRequest($request, $key);
+
+ if ($value->isEmpty()) {
+ return null;
+ }
+
+ return $value->getDictionary();
}
protected function readBoolFromRequest(
diff --git a/src/view/form/control/AphrontFormDateControl.php b/src/view/form/control/AphrontFormDateControl.php
--- a/src/view/form/control/AphrontFormDateControl.php
+++ b/src/view/form/control/AphrontFormDateControl.php
@@ -11,6 +11,7 @@
private $valueTime;
private $allowNull;
private $continueOnInvalidDate = false;
+ private $isDisabled;
public function setAllowNull($allow_null) {
$this->allowNull = $allow_null;
@@ -91,6 +92,8 @@
$this->valueMonth = $epoch->getValueMonth();
$this->valueDay = $epoch->getValueDay();
$this->valueTime = $epoch->getValueTime();
+ $this->allowNull = $epoch->getOptional();
+ $this->isDisabled = $epoch->isDisabled();
return parent::setValue($epoch->getEpoch());
}
@@ -183,6 +186,10 @@
}
}
+ if ($this->isDisabled) {
+ $disabled = 'disabled';
+ }
+
$min_year = $this->getMinYear();
$max_year = $this->getMaxYear();
@@ -227,7 +234,6 @@
array(
'name' => $this->getDayInputName(),
'sigil' => 'day-input',
- 'disabled' => $disabled,
));
$months_sel = AphrontFormSelectControl::renderSelectTag(
@@ -236,7 +242,6 @@
array(
'name' => $this->getMonthInputName(),
'sigil' => 'month-input',
- 'disabled' => $disabled,
));
$years_sel = AphrontFormSelectControl::renderSelectTag(
@@ -245,7 +250,6 @@
array(
'name' => $this->getYearInputName(),
'sigil' => 'year-input',
- 'disabled' => $disabled,
));
$cicon = id(new PHUIIconView())
@@ -268,16 +272,21 @@
'value' => $this->getTimeInputValue(),
'type' => 'text',
'class' => 'aphront-form-date-time-input',
- 'disabled' => $disabled,
),
'');
Javelin::initBehavior('fancy-datepicker', array());
+ $classes = array();
+ $classes[] = 'aphront-form-date-container';
+ if ($disabled) {
+ $classes[] = 'datepicker-disabled';
+ }
+
return javelin_tag(
'div',
array(
- 'class' => 'aphront-form-date-container',
+ 'class' => implode(' ', $classes),
'sigil' => 'phabricator-date-control',
'meta' => array(
'disabled' => (bool)$disabled,
diff --git a/src/view/form/control/AphrontFormDateControlValue.php b/src/view/form/control/AphrontFormDateControlValue.php
--- a/src/view/form/control/AphrontFormDateControlValue.php
+++ b/src/view/form/control/AphrontFormDateControlValue.php
@@ -6,9 +6,11 @@
private $valueMonth;
private $valueYear;
private $valueTime;
+ private $valueEnabled;
private $viewer;
private $zone;
+ private $optional;
public function getValueDay() {
return $this->valueDay;
@@ -27,27 +29,70 @@
}
public function isValid() {
+ if ($this->isDisabled()) {
+ return true;
+ }
return ($this->getEpoch() !== null);
}
+ public function isEmpty() {
+ if ($this->valueDay) {
+ return false;
+ }
+
+ if ($this->valueMonth) {
+ return false;
+ }
+
+ if ($this->valueYear) {
+ return false;
+ }
+
+ if ($this->valueTime) {
+ return false;
+ }
+
+ return true;
+ }
+
+ public function isDisabled() {
+ return ($this->optional && !$this->valueEnabled);
+ }
+
+ public function setEnabled($enabled) {
+ $this->valueEnabled = $enabled;
+ return $this;
+ }
+
+ public function setOptional($optional) {
+ $this->optional = $optional;
+ return $this;
+ }
+
+ public function getOptional() {
+ return $this->optional;
+ }
+
public static function newFromParts(
PhabricatorUser $viewer,
$year,
$month,
$day,
- $time = '12:00 AM') {
+ $time = null,
+ $enabled = true) {
$value = new AphrontFormDateControlValue();
$value->viewer = $viewer;
$value->valueYear = $year;
$value->valueMonth = $month;
$value->valueDay = $day;
- $value->valueTime = $time;
+ $value->valueTime = coalesce($time, '12:00 AM');
+ $value->valueEnabled = $enabled;
return $value;
}
- public static function newFromRequest($request, $key) {
+ public static function newFromRequest(AphrontRequest $request, $key) {
$value = new AphrontFormDateControlValue();
$value->viewer = $request->getViewer();
@@ -55,6 +100,7 @@
$value->valueMonth = $request->getInt($key.'_m');
$value->valueYear = $request->getInt($key.'_y');
$value->valueTime = $request->getStr($key.'_t');
+ $value->valueEnabled = $request->getStr($key.'_e');
return $value;
}
@@ -73,6 +119,44 @@
return $value;
}
+ public static function newFromDictionary(
+ PhabricatorUser $viewer,
+ array $dictionary) {
+ $value = new AphrontFormDateControlValue();
+ $value->viewer = $viewer;
+
+ $value->valueYear = idx($dictionary, 'y');
+ $value->valueMonth = idx($dictionary, 'm');
+ $value->valueDay = idx($dictionary, 'd');
+ $value->valueTime = idx($dictionary, 't');
+ $value->valueEnabled = idx($dictionary, 'e');
+
+ return $value;
+ }
+
+ public static function newFromWild(PhabricatorUser $viewer, $wild) {
+ if (is_array($wild)) {
+ return self::newFromDictionary($viewer, $wild);
+ } else if (is_numeric($wild)) {
+ return self::newFromEpoch($viewer, $wild);
+ } else {
+ throw new Exception(
+ pht(
+ 'Unable to construct a date value from value of type "%s".',
+ gettype($wild)));
+ }
+ }
+
+ public function getDictionary() {
+ return array(
+ 'y' => $this->valueYear,
+ 'm' => $this->valueMonth,
+ 'd' => $this->valueDay,
+ 't' => $this->valueTime,
+ 'e' => $this->valueEnabled,
+ );
+ }
+
private function formatTime($epoch, $format) {
return phabricator_format_local_time(
$epoch,
@@ -81,6 +165,10 @@
}
public function getEpoch() {
+ if ($this->isDisabled()) {
+ return null;
+ }
+
$year = $this->valueYear;
$month = $this->valueMonth;
$day = $this->valueDay;
diff --git a/webroot/rsrc/css/phui/phui-form-view.css b/webroot/rsrc/css/phui/phui-form-view.css
--- a/webroot/rsrc/css/phui/phui-form-view.css
+++ b/webroot/rsrc/css/phui/phui-form-view.css
@@ -446,6 +446,18 @@
border-radius: 3px;
}
+/* When the activation checkbox for the control is toggled off, visually
+disable the individual controls. We don't actually use the "disabled" property
+because we still want the values to submit. This is just a visual hint that
+the controls won't be used. The controls themselves are still live, work
+properly, and submit values. */
+.datepicker-disabled select,
+.datepicker-disabled .calendar-button,
+.datepicker-disabled input[type="text"] {
+ opacity: 0.5;
+}
+
+
.login-to-comment {
margin: 12px;
}
diff --git a/webroot/rsrc/js/core/behavior-fancy-datepicker.js b/webroot/rsrc/js/core/behavior-fancy-datepicker.js
--- a/webroot/rsrc/js/core/behavior-fancy-datepicker.js
+++ b/webroot/rsrc/js/core/behavior-fancy-datepicker.js
@@ -109,15 +109,8 @@
};
var redraw_inputs = function() {
- var inputs = get_inputs();
var disabled = JX.Stratcom.getData(root).disabled;
- for (var k in inputs) {
- if (disabled) {
- inputs[k].setAttribute('disabled', 'disabled');
- } else {
- inputs[k].removeAttribute('disabled');
- }
- }
+ JX.DOM.alterClass(root, 'datepicker-disabled', disabled);
var box = JX.DOM.scry(root, 'input', 'calendar-enable');
if (box.length) {

File Metadata

Mime Type
text/plain
Expires
Thu, Mar 20, 6:45 AM (5 h, 35 m ago)
Storage Engine
blob
Storage Format
Encrypted (AES-256-CBC)
Storage Handle
7225737
Default Alt Text
D12673.diff (14 KB)

Event Timeline