Page Menu
Home
Phabricator
Search
Configure Global Search
Log In
Files
F15410084
D12673.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Award Token
Flag For Later
Size
14 KB
Referenced Files
None
Subscribers
None
D12673.diff
View Options
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
Details
Attached
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)
Attached To
Mode
D12673: Manage date control enabled state as part of DateControlValue
Attached
Detach File
Event Timeline
Log In to Comment