1
0
Fork 0
mirror of https://we.phorge.it/source/phorge.git synced 2024-12-22 21:40:55 +01:00

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
This commit is contained in:
epriestley 2019-02-14 11:37:42 -08:00
parent 92abe3c8fb
commit aa470d2154
8 changed files with 141 additions and 40 deletions

View file

@ -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',
),

View file

@ -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;
}

View file

@ -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;
}
}

View file

@ -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(

View file

@ -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,

View file

@ -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;

View file

@ -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
};
},

View file

@ -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;