diff --git a/resources/celerity/map.php b/resources/celerity/map.php --- a/resources/celerity/map.php +++ b/resources/celerity/map.php @@ -9,8 +9,8 @@ 'names' => array( 'conpherence.pkg.css' => '3c8a0668', 'conpherence.pkg.js' => '020aebcf', - 'core.pkg.css' => 'f2319e1f', - 'core.pkg.js' => '5c737607', + 'core.pkg.css' => '261ee8cf', + 'core.pkg.js' => '5ace8a1e', 'differential.pkg.css' => 'b8df73d4', 'differential.pkg.js' => '67c9ea4c', 'diffusion.pkg.css' => '42c75c37', @@ -172,7 +172,7 @@ 'rsrc/css/phui/phui-segment-bar-view.css' => '5166b370', 'rsrc/css/phui/phui-spacing.css' => 'b05cadc3', 'rsrc/css/phui/phui-status.css' => 'e5ff8be0', - 'rsrc/css/phui/phui-tag-view.css' => 'a42fe34f', + 'rsrc/css/phui/phui-tag-view.css' => '29409667', 'rsrc/css/phui/phui-timeline-view.css' => '1e348e4b', 'rsrc/css/phui/phui-two-column-view.css' => '01e6991e', 'rsrc/css/phui/workboards/phui-workboard-color.css' => 'e86de308', @@ -441,7 +441,7 @@ 'rsrc/js/core/KeyboardShortcutManager.js' => '37b8a04a', 'rsrc/js/core/MultirowRowManager.js' => '5b54c823', 'rsrc/js/core/Notification.js' => 'a9b91e3f', - 'rsrc/js/core/Prefab.js' => 'bf457520', + 'rsrc/js/core/Prefab.js' => '5793d835', 'rsrc/js/core/ShapedRequest.js' => 'abf88db8', 'rsrc/js/core/TextAreaUtils.js' => 'f340a484', 'rsrc/js/core/Title.js' => '43bc9360', @@ -505,7 +505,7 @@ 'rsrc/js/phui/behavior-phui-timer-control.js' => 'f84bcbf4', 'rsrc/js/phuix/PHUIXActionListView.js' => 'c68f183f', 'rsrc/js/phuix/PHUIXActionView.js' => 'aaa08f3b', - 'rsrc/js/phuix/PHUIXAutocomplete.js' => '58cc4ab8', + 'rsrc/js/phuix/PHUIXAutocomplete.js' => '8f139ef0', 'rsrc/js/phuix/PHUIXButtonView.js' => '55a24e84', 'rsrc/js/phuix/PHUIXDropdownMenu.js' => 'bdce4d78', 'rsrc/js/phuix/PHUIXExample.js' => 'c2c500a7', @@ -771,7 +771,7 @@ 'phabricator-notification-menu-css' => 'e6962e89', 'phabricator-object-selector-css' => 'ee77366f', 'phabricator-phtize' => '2f1db1ed', - 'phabricator-prefab' => 'bf457520', + 'phabricator-prefab' => '5793d835', 'phabricator-remarkup-css' => '9e627d41', 'phabricator-search-results-css' => '9ea70ace', 'phabricator-shaped-request' => 'abf88db8', @@ -847,7 +847,7 @@ 'phui-segment-bar-view-css' => '5166b370', 'phui-spacing-css' => 'b05cadc3', 'phui-status-list-view-css' => 'e5ff8be0', - 'phui-tag-view-css' => 'a42fe34f', + 'phui-tag-view-css' => '29409667', 'phui-theme-css' => '35883b37', 'phui-timeline-view-css' => '1e348e4b', 'phui-two-column-view-css' => '01e6991e', @@ -857,7 +857,7 @@ 'phui-workpanel-view-css' => 'bd546a49', 'phuix-action-list-view' => 'c68f183f', 'phuix-action-view' => 'aaa08f3b', - 'phuix-autocomplete' => '58cc4ab8', + 'phuix-autocomplete' => '8f139ef0', 'phuix-button-view' => '55a24e84', 'phuix-dropdown-menu' => 'bdce4d78', 'phuix-form-control-view' => '38c1f3fb', @@ -1354,6 +1354,18 @@ 'javelin-stratcom', 'javelin-dom', ), + '5793d835' => array( + 'javelin-install', + 'javelin-util', + 'javelin-dom', + 'javelin-typeahead', + 'javelin-tokenizer', + 'javelin-typeahead-preloaded-source', + 'javelin-typeahead-ondemand-source', + 'javelin-dom', + 'javelin-stratcom', + 'javelin-util', + ), '5803b9e7' => array( 'javelin-behavior', 'javelin-util', @@ -1362,12 +1374,6 @@ 'javelin-vector', 'javelin-typeahead-static-source', ), - '58cc4ab8' => array( - 'javelin-install', - 'javelin-dom', - 'phuix-icon-view', - 'phabricator-prefab', - ), '5902260c' => array( 'javelin-util', 'javelin-magical-init', @@ -1608,6 +1614,12 @@ '8e2d9a28' => array( 'phui-theme-css', ), + '8f139ef0' => array( + 'javelin-install', + 'javelin-dom', + 'phuix-icon-view', + 'phabricator-prefab', + ), '8f959ad0' => array( 'javelin-behavior', 'javelin-dom', @@ -1895,18 +1907,6 @@ 'javelin-vector', 'javelin-stratcom', ), - 'bf457520' => array( - 'javelin-install', - 'javelin-util', - 'javelin-dom', - 'javelin-typeahead', - 'javelin-tokenizer', - 'javelin-typeahead-preloaded-source', - 'javelin-typeahead-ondemand-source', - 'javelin-dom', - 'javelin-stratcom', - 'javelin-util', - ), 'c03f2fb4' => array( 'javelin-install', ), diff --git a/src/applications/people/typeahead/PhabricatorPeopleDatasource.php b/src/applications/people/typeahead/PhabricatorPeopleDatasource.php --- a/src/applications/people/typeahead/PhabricatorPeopleDatasource.php +++ b/src/applications/people/typeahead/PhabricatorPeopleDatasource.php @@ -19,7 +19,8 @@ $viewer = $this->getViewer(); $query = id(new PhabricatorPeopleQuery()) - ->setOrderVector(array('username')); + ->setOrderVector(array('username')) + ->needAvailability(true); if ($this->getPhase() == self::PHASE_PREFIX) { $prefix = $this->getPrefixQuery(); @@ -96,6 +97,14 @@ $result->setDisplayType($display_type); } + $until = $user->getAwayUntil(); + if ($until) { + $availability = $user->getDisplayAvailability(); + $color = PhabricatorCalendarEventInvitee::getAvailabilityColor( + $availability); + $result->setAvailabilityColor($color); + } + $results[] = $result; } diff --git a/src/applications/typeahead/storage/PhabricatorTypeaheadResult.php b/src/applications/typeahead/storage/PhabricatorTypeaheadResult.php --- a/src/applications/typeahead/storage/PhabricatorTypeaheadResult.php +++ b/src/applications/typeahead/storage/PhabricatorTypeaheadResult.php @@ -19,6 +19,7 @@ private $autocomplete; private $attributes = array(); private $phase; + private $availabilityColor; public function setIcon($icon) { $this->icon = $icon; @@ -156,6 +157,7 @@ $this->unique ? 1 : null, $this->autocomplete, $this->phase, + $this->availabilityColor, ); while (end($data) === null) { array_pop($data); @@ -222,4 +224,13 @@ return $this->phase; } + public function setAvailabilityColor($availability_color) { + $this->availabilityColor = $availability_color; + return $this; + } + + public function getAvailabilityColor() { + return $this->availabilityColor; + } + } diff --git a/src/applications/typeahead/view/PhabricatorTypeaheadTokenView.php b/src/applications/typeahead/view/PhabricatorTypeaheadTokenView.php --- a/src/applications/typeahead/view/PhabricatorTypeaheadTokenView.php +++ b/src/applications/typeahead/view/PhabricatorTypeaheadTokenView.php @@ -14,6 +14,7 @@ private $inputName; private $value; private $tokenType = self::TYPE_OBJECT; + private $availabilityColor; public static function newFromTypeaheadResult( PhabricatorTypeaheadResult $result) { @@ -41,6 +42,21 @@ $token->setColor($handle->getTagColor()); } + $availability = $handle->getAvailability(); + $color = null; + switch ($availability) { + case PhabricatorObjectHandle::AVAILABILITY_PARTIAL: + $color = PHUITagView::COLOR_ORANGE; + break; + case PhabricatorObjectHandle::AVAILABILITY_NONE: + $color = PHUITagView::COLOR_RED; + break; + } + + if ($color !== null) { + $token->setAvailabilityColor($color); + } + return $token; } @@ -106,6 +122,15 @@ return 'a'; } + public function setAvailabilityColor($availability_color) { + $this->availabilityColor = $availability_color; + return $this; + } + + public function getAvailabilityColor() { + return $this->availabilityColor; + } + protected function getTagAttributes() { $classes = array(); $classes[] = 'jx-tokenizer-token'; @@ -139,20 +164,32 @@ $value = $this->getValue(); + $availability = null; + $availability_color = $this->getAvailabilityColor(); + if ($availability_color) { + $availability = phutil_tag( + 'span', + array( + 'class' => 'phui-tag-dot phui-tag-color-'.$availability_color, + )); + } + + $icon_view = null; $icon = $this->getIcon(); if ($icon) { - $value = array( - phutil_tag( - 'span', - array( - 'class' => 'phui-icon-view phui-font-fa '.$icon, - )), - $value, - ); + $icon_view = phutil_tag( + 'span', + array( + 'class' => 'phui-icon-view phui-font-fa '.$icon, + )); } return array( - $value, + array( + $icon_view, + $availability, + $value, + ), phutil_tag( 'input', array( diff --git a/src/view/form/control/AphrontFormTokenizerControl.php b/src/view/form/control/AphrontFormTokenizerControl.php --- a/src/view/form/control/AphrontFormTokenizerControl.php +++ b/src/view/form/control/AphrontFormTokenizerControl.php @@ -108,6 +108,10 @@ 'icons' => mpull($tokens, 'getIcon', 'getKey'), 'types' => mpull($tokens, 'getTokenType', 'getKey'), 'colors' => mpull($tokens, 'getColor', 'getKey'), + 'availabilityColors' => mpull( + $tokens, + 'getAvailabilityColor', + 'getKey'), 'limit' => $this->limit, 'username' => $username, 'placeholder' => $placeholder, diff --git a/webroot/rsrc/css/phui/phui-tag-view.css b/webroot/rsrc/css/phui/phui-tag-view.css --- a/webroot/rsrc/css/phui/phui-tag-view.css +++ b/webroot/rsrc/css/phui/phui-tag-view.css @@ -54,6 +54,14 @@ border: 1px solid transparent; } +.tokenizer-result .phui-tag-dot { + margin-right: 6px; +} + +.jx-tokenizer-token .phui-tag-dot { + margin-left: 2px; +} + .phui-tag-type-state { color: #ffffff; text-shadow: rgba(100, 100, 100, 0.40) 0px -1px 1px; diff --git a/webroot/rsrc/js/core/Prefab.js b/webroot/rsrc/js/core/Prefab.js --- a/webroot/rsrc/js/core/Prefab.js +++ b/webroot/rsrc/js/core/Prefab.js @@ -125,15 +125,18 @@ var icon; var type; var color; + var availability_color; if (result) { icon = result.icon; value = result.displayName; type = result.tokenType; color = result.color; + availability_color = result.availabilityColor; } else { icon = (config.icons || {})[key]; type = (config.types || {})[key]; color = (config.colors || {})[key]; + availability_color = (config.availabilityColors || {})[key]; } if (icon) { @@ -147,7 +150,16 @@ JX.DOM.alterClass(container, color, true); } - return [icon, value]; + var dot; + if (availability_color) { + dot = JX.$N( + 'span', + { + className: 'phui-tag-dot phui-tag-color-' + availability_color + }); + } + + return [icon, dot, value]; }); if (config.placeholder) { @@ -275,10 +287,20 @@ icon_ui = JX.Prefab._renderIcon(icon); } + var availability_ui; + var availability_color = fields[16]; + if (availability_color) { + availability_ui = JX.$N( + 'span', + { + className: 'phui-tag-dot phui-tag-color-' + availability_color + }); + } + var display = JX.$N( 'div', {className: 'tokenizer-result'}, - [icon_ui, fields[4] || fields[0], closed_ui]); + [icon_ui, availability_ui, fields[4] || fields[0], closed_ui]); if (closed) { JX.DOM.alterClass(display, 'tokenizer-result-closed', true); } @@ -300,7 +322,8 @@ tokenType: fields[12], unique: fields[13] || false, autocomplete: fields[14], - sort: JX.TypeaheadNormalizer.normalize(fields[0]) + sort: JX.TypeaheadNormalizer.normalize(fields[0]), + availabilityColor: availability_color }; }, diff --git a/webroot/rsrc/js/phuix/PHUIXAutocomplete.js b/webroot/rsrc/js/phuix/PHUIXAutocomplete.js --- a/webroot/rsrc/js/phuix/PHUIXAutocomplete.js +++ b/webroot/rsrc/js/phuix/PHUIXAutocomplete.js @@ -185,7 +185,16 @@ .getNode(); } - var display = JX.$N('span', {}, [icon, map.displayName]); + var dot; + if (map.availabilityColor) { + dot = JX.$N( + 'span', + { + className: 'phui-tag-dot phui-tag-color-' + map.availabilityColor + }); + } + + var display = JX.$N('span', {}, [icon, dot, map.displayName]); JX.DOM.alterClass(display, 'tokenizer-result-closed', !!map.closed); map.display = display;