1
0
Fork 0
mirror of https://we.phorge.it/source/phorge.git synced 2024-12-27 07:50:57 +01:00

Render browse results with global result style

Summary:
Ref T11034. This seems a little more promising. Two problems at the moment:

  - This doesn't actually provide any useful information at all right now.
  - Many object types have no profile images.

Test Plan:
{F1695254}

{F1695255}

Reviewers: chad

Reviewed By: chad

Maniphest Tasks: T11034

Differential Revision: https://secure.phabricator.com/D16155
This commit is contained in:
epriestley 2016-06-20 13:52:18 -07:00
parent 851aba80ce
commit 6f275ba144
23 changed files with 258 additions and 52 deletions

View file

@ -28,7 +28,7 @@ return array(
'rsrc/css/aphront/table-view.css' => '9258e19f',
'rsrc/css/aphront/tokenizer.css' => '056da01b',
'rsrc/css/aphront/tooltip.css' => '1a07aea8',
'rsrc/css/aphront/typeahead-browse.css' => 'd8581d2c',
'rsrc/css/aphront/typeahead-browse.css' => '8904346a',
'rsrc/css/aphront/typeahead.css' => 'd4f16145',
'rsrc/css/application/almanac/almanac.css' => 'dbb9b3af',
'rsrc/css/application/auth/auth.css' => '0877ed6e',
@ -889,7 +889,7 @@ return array(
'syntax-default-css' => '9923583c',
'syntax-highlighting-css' => '9fc496d5',
'tokens-css' => '3d0f239e',
'typeahead-browse-css' => 'd8581d2c',
'typeahead-browse-css' => '8904346a',
'unhandled-exception-css' => '4c96257a',
),
'requires' => array(

View file

@ -31,24 +31,50 @@ final class DiffusionRepositoryDatasource
"phabricator-search-icon phui-font-fa phui-icon-view {$type_icon}";
$results = array();
foreach ($repos as $repo) {
$display_name = $repo->getMonogram().' '.$repo->getName();
foreach ($repos as $repository) {
$monogram = $repository->getMonogram();
$name = $repository->getName();
$name = $display_name;
$slug = $repo->getRepositorySlug();
$display_name = "{$monogram} {$name}";
$parts = array();
$parts[] = $name;
$slug = $repository->getRepositorySlug();
if (strlen($slug)) {
$name = "{$name} {$slug}";
$parts[] = $slug;
}
$results[] = id(new PhabricatorTypeaheadResult())
$callsign = $repository->getCallsign();
if ($callsign) {
$parts[] = $callsign;
}
foreach ($repository->getAllMonograms() as $monogram) {
$parts[] = $monogram;
}
$name = implode(' ', $parts);
$vcs = $repository->getVersionControlSystem();
$vcs_type = PhabricatorRepositoryType::getNameForRepositoryType($vcs);
$result = id(new PhabricatorTypeaheadResult())
->setName($name)
->setDisplayName($display_name)
->setURI($repo->getURI())
->setPHID($repo->getPHID())
->setPriorityString($repo->getMonogram())
->setURI($repository->getURI())
->setPHID($repository->getPHID())
->setPriorityString($repository->getMonogram())
->setPriorityType('repo')
->setImageSprite($image_sprite)
->setDisplayType(pht('Repository'));
->setDisplayType(pht('Repository'))
->addAttribute($vcs_type);
if (!$repository->isTracked()) {
$result->setClosed(pht('Inactive'));
}
$results[] = $result;
}
return $results;

View file

@ -43,7 +43,10 @@ final class DiffusionTaggedRepositoriesFunctionDatasource
->setColor(null)
->setPHID('tagged('.$result->getPHID().')')
->setDisplayName(pht('Tagged: %s', $result->getDisplayName()))
->setName('tagged '.$result->getName());
->setName('tagged '.$result->getName())
->resetAttributes()
->addAttribute(pht('Function'))
->addAttribute(pht('Select repositories tagged with this project.'));
}
return $results;

View file

@ -7,6 +7,10 @@ final class DrydockBlueprintDatasource
return pht('Type a blueprint name...');
}
public function getBrowseTitle() {
return pht('Browse Blueprints');
}
public function getDatasourceApplicationClass() {
return 'PhabricatorDrydockApplication';
}
@ -37,6 +41,9 @@ final class DrydockBlueprintDatasource
$result->setClosed(pht('Disabled'));
}
$result->addAttribute(
$blueprint->getImplementation()->getBlueprintName());
$results[] = $result;
}

View file

@ -67,7 +67,8 @@ final class ManiphestTaskClosedStatusDatasource
->setName($name.' closed')
->setDisplayName($name)
->setPHID(self::FUNCTION_TOKEN)
->setUnique(true);
->setUnique(true)
->addAttribute(pht('Select any closed status.'));
}
}

View file

@ -67,7 +67,8 @@ final class ManiphestTaskOpenStatusDatasource
->setName($name.' open')
->setDisplayName($name)
->setPHID(self::FUNCTION_TOKEN)
->setUnique(true);
->setUnique(true)
->addAttribute(pht('Select any open status.'));
}
}

View file

@ -32,7 +32,8 @@ final class ManiphestTaskPriorityDatasource
$result = id(new PhabricatorTypeaheadResult())
->setIcon(ManiphestTaskPriority::getTaskPriorityIcon($value))
->setPHID($value)
->setName($name);
->setName($name)
->addAttribute(pht('Priority'));
if (ManiphestTaskPriority::isDisabledPriority($value)) {
$result->setClosed(pht('Disabled'));

View file

@ -35,6 +35,12 @@ final class ManiphestTaskStatusDatasource
->setPHID($value)
->setName($name);
if (ManiphestTaskStatus::isOpenStatus($value)) {
$result->addAttribute(pht('Open Status'));
} else {
$result->addAttribute(pht('Closed Status'));
}
if (ManiphestTaskStatus::isDisabledStatus($value)) {
$result->setClosed(pht('Disabled'));
}

View file

@ -62,7 +62,8 @@ final class PhabricatorPeopleAnyOwnerDatasource
->setDisplayName($name)
->setIcon('fa-certificate')
->setPHID(self::FUNCTION_TOKEN)
->setUnique(true);
->setUnique(true)
->addAttribute(pht('Select results with any owner.'));
}
}

View file

@ -3,18 +3,6 @@
final class PhabricatorPeopleDatasource
extends PhabricatorTypeaheadDatasource {
private $enrichResults;
/**
* Controls enriched rendering, for global search. This is a bit hacky and
* should probably be handled in a more general way, but is fairly reasonable
* for now.
*/
public function setEnrichResults($enrich) {
$this->enrichResults = $enrich;
return $this;
}
public function getBrowseTitle() {
return pht('Browse Users');
}
@ -40,7 +28,9 @@ final class PhabricatorPeopleDatasource
$users = $this->executeQuery($query);
if ($this->enrichResults && $users) {
$is_browse = $this->getIsBrowse();
if ($is_browse && $users) {
$phids = mpull($users, 'getPHID');
$handles = id(new PhabricatorHandleQuery())
->setViewer($viewer)
@ -50,6 +40,8 @@ final class PhabricatorPeopleDatasource
$results = array();
foreach ($users as $user) {
$phid = $user->getPHID();
$closed = null;
if ($user->getIsDisabled()) {
$closed = pht('Disabled');
@ -64,7 +56,7 @@ final class PhabricatorPeopleDatasource
$result = id(new PhabricatorTypeaheadResult())
->setName($user->getFullName())
->setURI('/p/'.$username.'/')
->setPHID($user->getPHID())
->setPHID($phid)
->setPriorityString($username)
->setPriorityType('user')
->setAutocomplete('@'.$username)
@ -74,13 +66,29 @@ final class PhabricatorPeopleDatasource
$result->setIcon('fa-envelope-o');
}
if ($this->enrichResults) {
$display_type = pht('User');
if ($is_browse) {
$handle = $handles[$phid];
$result
->setIcon($handle->getIcon())
->setImageURI($handle->getImageURI())
->addAttribute($handle->getSubtitle());
if ($user->getIsAdmin()) {
$result->addAttribute(
array(
id(new PHUIIconView())->setIcon('fa-star'),
' ',
pht('Administrator'),
));
}
if ($user->getIsAdmin()) {
$display_type = pht('Administrator');
} else {
$display_type = pht('User');
}
$result->setDisplayType($display_type);
$result->setImageURI($handles[$user->getPHID()]->getImageURI());
}
$results[] = $result;

View file

@ -69,7 +69,8 @@ final class PhabricatorPeopleNoOwnerDatasource
->setDisplayName($name)
->setIcon('fa-ban')
->setPHID('none()')
->setUnique(true);
->setUnique(true)
->addAttribute(pht('Select results with no owner.'));
}
}

View file

@ -74,7 +74,8 @@ final class PhabricatorViewerDatasource
->setName(pht('Current Viewer'))
->setPHID('viewer()')
->setIcon('fa-user')
->setUnique(true);
->setUnique(true)
->addAttribute(pht('Select current viewer.'));
}
}

View file

@ -55,9 +55,25 @@ final class PhabricatorProjectDatasource
$has_cols = array_fill_keys(array_keys($projs), true);
}
$is_browse = $this->getIsBrowse();
if ($is_browse && $projs) {
// TODO: This is a little ad-hoc, but we don't currently have
// infrastructure for bulk querying custom fields efficiently.
$table = new PhabricatorProjectCustomFieldStorage();
$descriptions = $table->loadAllWhere(
'objectPHID IN (%Ls) AND fieldIndex = %s',
array_keys($projs),
PhabricatorHash::digestForIndex('std:project:internal:description'));
$descriptions = mpull($descriptions, 'getFieldValue', 'getObjectPHID');
} else {
$descriptions = array();
}
$results = array();
foreach ($projs as $proj) {
if (!isset($has_cols[$proj->getPHID()])) {
$phid = $proj->getPHID();
if (!isset($has_cols[$phid])) {
continue;
}
@ -99,7 +115,7 @@ final class PhabricatorProjectDatasource
->setDisplayName($proj->getDisplayName())
->setDisplayType($proj->getDisplayIconName())
->setURI($proj->getURI())
->setPHID($proj->getPHID())
->setPHID($phid)
->setIcon($proj->getDisplayIconIcon())
->setColor($proj->getColor())
->setPriorityType('proj')
@ -111,6 +127,16 @@ final class PhabricatorProjectDatasource
$proj_result->setImageURI($proj->getProfileImageURI());
if ($is_browse) {
$proj_result->addAttribute($proj->getDisplayIconName());
$description = idx($descriptions, $phid);
if (strlen($description)) {
$summary = PhabricatorMarkupEngine::summarize($description);
$proj_result->addAttribute($summary);
}
}
$results[] = $proj_result;
}

View file

@ -86,20 +86,24 @@ final class PhabricatorProjectLogicalOrNotDatasource
$result
->setTokenType(PhabricatorTypeaheadTokenView::TYPE_FUNCTION)
->setIcon('fa-asterisk')
->setColor(null);
->setColor(null)
->resetAttributes()
->addAttribute(pht('Function'));
if ($return_any) {
$return[] = id(clone $result)
->setPHID('any('.$result->getPHID().')')
->setDisplayName(pht('In Any: %s', $result->getDisplayName()))
->setName('any '.$result->getName());
->setName('any '.$result->getName())
->addAttribute(pht('Include results tagged with this project.'));
}
if ($return_not) {
$return[] = id(clone $result)
->setPHID('not('.$result->getPHID().')')
->setDisplayName(pht('Not In: %s', $result->getDisplayName()))
->setName('not '.$result->getName());
->setName('not '.$result->getName())
->addAttribute(pht('Exclude results tagged with this project.'));
}
}

View file

@ -96,7 +96,8 @@ final class PhabricatorProjectLogicalViewerDatasource
->setName(pht('Current Viewer\'s Projects'))
->setPHID('viewerprojects()')
->setIcon('fa-asterisk')
->setUnique(true);
->setUnique(true)
->addAttribute(pht('Select projects current viewer is a member of.'));
}
}

View file

@ -44,7 +44,10 @@ final class PhabricatorProjectMembersDatasource
->setColor(null)
->setPHID('members('.$result->getPHID().')')
->setDisplayName(pht('Members: %s', $result->getDisplayName()))
->setName($result->getName().' members');
->setName($result->getName().' members')
->resetAttributes()
->addAttribute(pht('Function'))
->addAttribute(pht('Select project members.'));
}
return $results;

View file

@ -68,7 +68,8 @@ final class PhabricatorProjectNoProjectsDatasource
->setPHID('null()')
->setIcon('fa-ban')
->setName('null '.$name)
->setDisplayName($name);
->setDisplayName($name)
->addAttribute(pht('Select results with no tags.'));
}
}

View file

@ -16,14 +16,22 @@ final class PhabricatorSearchDatasource
}
public function getComponentDatasources() {
return array(
id(new PhabricatorPeopleDatasource())->setEnrichResults(true),
$sources = array(
new PhabricatorPeopleDatasource(),
new PhabricatorProjectDatasource(),
new PhabricatorApplicationDatasource(),
new PhabricatorTypeaheadMonogramDatasource(),
new DiffusionRepositoryDatasource(),
new DiffusionSymbolDatasource(),
);
// These results are always rendered in the full browse display mode, so
// set the browse flag on all component sources.
foreach ($sources as $source) {
$source->setIsBrowse(true);
}
return $sources;
}
}

View file

@ -65,7 +65,8 @@ final class PhabricatorTypeaheadModularDatasourceController
}
$composite
->setOffset($offset);
->setOffset($offset)
->setIsBrowse(true);
}
$results = $composite->loadResults();
@ -142,8 +143,7 @@ final class PhabricatorTypeaheadModularDatasourceController
$items = array();
foreach ($results as $result) {
$token = PhabricatorTypeaheadTokenView::newFromTypeaheadResult(
$result);
$information = $this->renderBrowseResult($result);
// Disable already-selected tokens.
$disabled = isset($exclude[$result->getPHID()]);
@ -167,8 +167,8 @@ final class PhabricatorTypeaheadModularDatasourceController
'class' => 'typeahead-browse-item grouped',
),
array(
$token,
$button,
$information,
));
}
@ -350,4 +350,56 @@ final class PhabricatorTypeaheadModularDatasourceController
->appendChild($view);
}
private function renderBrowseResult(PhabricatorTypeaheadResult $result) {
$class = array();
$style = array();
$separator = " \xC2\xB7 ";
$class[] = 'phabricator-main-search-typeahead-result';
$name = phutil_tag(
'div',
array(
'class' => 'result-name',
),
$result->getDisplayName());
$icon = $result->getIcon();
$icon = id(new PHUIIconView())->setIcon($icon);
$attributes = $result->getAttributes();
$attributes = phutil_implode_html($separator, $attributes);
$attributes = array($icon, ' ', $attributes);
$closed = $result->getClosed();
if ($closed) {
$class[] = 'result-closed';
$attributes = array($closed, $separator, $attributes);
}
$attributes = phutil_tag(
'div',
array(
'class' => 'result-type',
),
$attributes);
$image = $result->getImageURI();
if ($image) {
$style[] = 'background-image: url('.$image.');';
$class[] = 'has-image';
}
return phutil_tag(
'div',
array(
'class' => implode(' ', $class),
'style' => implode(' ', $style),
),
array(
$name,
$attributes,
));
}
}

View file

@ -37,6 +37,7 @@ abstract class PhabricatorTypeaheadCompositeDatasource
}
$stack = $this->getFunctionStack();
$is_browse = $this->getIsBrowse();
$results = array();
foreach ($this->getUsableDatasources() as $source) {
@ -70,6 +71,10 @@ abstract class PhabricatorTypeaheadCompositeDatasource
$source->setLimit($offset + $limit);
}
if ($is_browse) {
$source->setIsBrowse(true);
}
$source_results = $source->loadResults();
$source_results = $source->didLoadResults($source_results);
$results[] = $source_results;

View file

@ -12,6 +12,7 @@ abstract class PhabricatorTypeaheadDatasource extends Phobject {
private $limit;
private $parameters = array();
private $functionStack = array();
private $isBrowse;
public function setLimit($limit) {
$this->limit = $limit;
@ -71,6 +72,15 @@ abstract class PhabricatorTypeaheadDatasource extends Phobject {
return idx($this->parameters, $name, $default);
}
public function setIsBrowse($is_browse) {
$this->isBrowse = $is_browse;
return $this;
}
public function getIsBrowse() {
return $this->isBrowse;
}
public function getDatasourceURI() {
$uri = new PhutilURI('/typeahead/class/'.get_class($this).'/');
$uri->setQueryParams($this->parameters);
@ -199,7 +209,8 @@ abstract class PhabricatorTypeaheadDatasource extends Phobject {
protected function newFunctionResult() {
return id(new PhabricatorTypeaheadResult())
->setTokenType(PhabricatorTypeaheadTokenView::TYPE_FUNCTION)
->setIcon('fa-asterisk');
->setIcon('fa-asterisk')
->addAttribute(pht('Function'));
}
public function newInvalidToken($name) {

View file

@ -17,6 +17,7 @@ final class PhabricatorTypeaheadResult extends Phobject {
private $tokenType;
private $unique;
private $autocomplete;
private $attributes = array();
public function setIcon($icon) {
$this->icon = $icon;
@ -188,4 +189,26 @@ final class PhabricatorTypeaheadResult extends Phobject {
return null;
}
public function getImageURI() {
return $this->imageURI;
}
public function getClosed() {
return $this->closed;
}
public function resetAttributes() {
$this->attributes = array();
return $this;
}
public function getAttributes() {
return $this->attributes;
}
public function addAttribute($attribute) {
$this->attributes[] = $attribute;
return $this;
}
}

View file

@ -57,10 +57,26 @@ input.typeahead-browse-input {
.typeahead-browse-item button {
float: right;
margin: 2px 6px;
margin: 8px 6px 0;
}
.typeahead-browse-item a.jx-tokenizer-token {
margin-top: 1px;
margin-left: 6px;
}
.typeahead-browse-item .phabricator-main-search-typeahead-result {
margin: 2px 0;
padding: 0 8px;
}
.typeahead-browse-item .phabricator-main-search-typeahead-result.has-image {
padding-left: 48px;
}
.typeahead-browse-item
.phabricator-main-search-typeahead-result.result-closed
.result-name {
text-decoration: line-through;
color: {$lightgreytext};
}