Commit aa470d21 authored by epriestley's avatar epriestley
Browse files

Show user availability dots (red = away, orange = busy) in typeaheads,...

Show user availability dots (red = away, orange = busy) in typeaheads, tokenizer tokens, and autocompletes

Summary:
Ref T13249. See PHI810. We currently show availability dots in some interfaces (timeline, mentions) but not others (typeheads/tokenizers).

They're potentially quite useful in tokenizers, e.g. when assigning tasks to someone or requesting reviews. Show them in more places.

(The actual rendering here isn't terribly clean, and it would be great to try to unify all these various behaviors some day.)

Test Plan:
{F6212044}

{F6212045}

Reviewers: amckinley

Reviewed By: amckinley

Maniphest Tasks: T13249

Differential Revision: https://secure.phabricator.com/D20173
parent 92abe3c8
......@@ -9,8 +9,8 @@ return array(
'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 @@ return array(
'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 @@ return array(
'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 @@ return array(
'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 @@ return array(
'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 @@ return array(
'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 @@ return array(
'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 @@ return array(
'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 @@ return array(
'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 @@ return array(
'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 @@ return array(
'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',
),
......
......@@ -19,7 +19,8 @@ final class PhabricatorPeopleDatasource
$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 @@ final class PhabricatorPeopleDatasource
$result->setDisplayType($display_type);
}
$until = $user->getAwayUntil();
if ($until) {
$availability = $user->getDisplayAvailability();
$color = PhabricatorCalendarEventInvitee::getAvailabilityColor(
$availability);
$result->setAvailabilityColor($color);
}
$results[] = $result;
}
......
......@@ -19,6 +19,7 @@ final class PhabricatorTypeaheadResult extends Phobject {
private $autocomplete;
private $attributes = array();
private $phase;
private $availabilityColor;
public function setIcon($icon) {
$this->icon = $icon;
......@@ -156,6 +157,7 @@ final class PhabricatorTypeaheadResult extends Phobject {
$this->unique ? 1 : null,
$this->autocomplete,
$this->phase,
$this->availabilityColor,
);
while (end($data) === null) {
array_pop($data);
......@@ -222,4 +224,13 @@ final class PhabricatorTypeaheadResult extends Phobject {
return $this->phase;
}
public function setAvailabilityColor($availability_color) {
$this->availabilityColor = $availability_color;
return $this;
}
public function getAvailabilityColor() {
return $this->availabilityColor;
}
}
......@@ -14,6 +14,7 @@ final class PhabricatorTypeaheadTokenView
private $inputName;
private $value;
private $tokenType = self::TYPE_OBJECT;
private $availabilityColor;
public static function newFromTypeaheadResult(
PhabricatorTypeaheadResult $result) {
......@@ -41,6 +42,21 @@ final class PhabricatorTypeaheadTokenView
$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 @@ final class PhabricatorTypeaheadTokenView
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 @@ final class PhabricatorTypeaheadTokenView
$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(
......
......@@ -108,6 +108,10 @@ final class AphrontFormTokenizerControl extends AphrontFormControl {
'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,
......
......@@ -54,6 +54,14 @@ a.phui-tag-view:hover {
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;
......
......@@ -125,15 +125,18 @@ JX.install('Prefab', {
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.install('Prefab', {
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 @@ JX.install('Prefab', {
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 @@ JX.install('Prefab', {
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
};
},
......
......@@ -185,7 +185,16 @@ JX.install('PHUIXAutocomplete', {
.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;
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment