Use a typeahead for "document types" in global search
Summary:
  - Now that we have "browse", this is a much more reasonable control for random sets of things.
  - The new explicit search scope selector reduces the need to fiddle with this field manually, too.
Test Plan:
{F379292}
{F379293}
Reviewers: chad, btrahan
Reviewed By: btrahan
Subscribers: epriestley
Differential Revision: https://secure.phabricator.com/D12510
			
			
This commit is contained in:
		| @@ -8,8 +8,8 @@ | |||||||
| return array( | return array( | ||||||
|   'names' => array( |   'names' => array( | ||||||
|     'core.pkg.css' => 'f7d01efc', |     'core.pkg.css' => 'f7d01efc', | ||||||
|     'core.pkg.js' => 'a1f9db42', |     'core.pkg.js' => 'd3f3a35c', | ||||||
|     'darkconsole.pkg.js' => '8ab24e01', |     'darkconsole.pkg.js' => 'b0a3ba93', | ||||||
|     'differential.pkg.css' => '3500921f', |     'differential.pkg.css' => '3500921f', | ||||||
|     'differential.pkg.js' => 'c0506961', |     'differential.pkg.js' => 'c0506961', | ||||||
|     'diffusion.pkg.css' => '591664fa', |     'diffusion.pkg.css' => '591664fa', | ||||||
| @@ -350,7 +350,7 @@ return array( | |||||||
|     'rsrc/image/texture/table_header_hover.png' => '038ec3b9', |     'rsrc/image/texture/table_header_hover.png' => '038ec3b9', | ||||||
|     'rsrc/image/texture/table_header_tall.png' => 'd56b434f', |     'rsrc/image/texture/table_header_tall.png' => 'd56b434f', | ||||||
|     'rsrc/js/application/aphlict/Aphlict.js' => '30a6303c', |     'rsrc/js/application/aphlict/Aphlict.js' => '30a6303c', | ||||||
|     'rsrc/js/application/aphlict/behavior-aphlict-dropdown.js' => '572566ae', |     'rsrc/js/application/aphlict/behavior-aphlict-dropdown.js' => 'ee37f73a', | ||||||
|     'rsrc/js/application/aphlict/behavior-aphlict-listen.js' => 'b1a59974', |     'rsrc/js/application/aphlict/behavior-aphlict-listen.js' => 'b1a59974', | ||||||
|     'rsrc/js/application/aphlict/behavior-aphlict-status.js' => 'ea681761', |     'rsrc/js/application/aphlict/behavior-aphlict-status.js' => 'ea681761', | ||||||
|     'rsrc/js/application/auth/behavior-persona-login.js' => '9414ff18', |     'rsrc/js/application/auth/behavior-persona-login.js' => '9414ff18', | ||||||
| @@ -460,7 +460,7 @@ return array( | |||||||
|     'rsrc/js/core/behavior-autofocus.js' => '7319e029', |     'rsrc/js/core/behavior-autofocus.js' => '7319e029', | ||||||
|     'rsrc/js/core/behavior-choose-control.js' => '6153c708', |     'rsrc/js/core/behavior-choose-control.js' => '6153c708', | ||||||
|     'rsrc/js/core/behavior-crop.js' => 'fa0f4fc2', |     'rsrc/js/core/behavior-crop.js' => 'fa0f4fc2', | ||||||
|     'rsrc/js/core/behavior-dark-console.js' => '08883e8b', |     'rsrc/js/core/behavior-dark-console.js' => 'b8df5663', | ||||||
|     'rsrc/js/core/behavior-device.js' => 'a205cf28', |     'rsrc/js/core/behavior-device.js' => 'a205cf28', | ||||||
|     'rsrc/js/core/behavior-drag-and-drop-textarea.js' => '6d49590e', |     'rsrc/js/core/behavior-drag-and-drop-textarea.js' => '6d49590e', | ||||||
|     'rsrc/js/core/behavior-error-log.js' => '6882e80a', |     'rsrc/js/core/behavior-error-log.js' => '6882e80a', | ||||||
| @@ -550,7 +550,7 @@ return array( | |||||||
|     'inline-comment-summary-css' => 'eb5f8e8c', |     'inline-comment-summary-css' => 'eb5f8e8c', | ||||||
|     'javelin-aphlict' => '30a6303c', |     'javelin-aphlict' => '30a6303c', | ||||||
|     'javelin-behavior' => '61cbc29a', |     'javelin-behavior' => '61cbc29a', | ||||||
|     'javelin-behavior-aphlict-dropdown' => '572566ae', |     'javelin-behavior-aphlict-dropdown' => 'ee37f73a', | ||||||
|     'javelin-behavior-aphlict-listen' => 'b1a59974', |     'javelin-behavior-aphlict-listen' => 'b1a59974', | ||||||
|     'javelin-behavior-aphlict-status' => 'ea681761', |     'javelin-behavior-aphlict-status' => 'ea681761', | ||||||
|     'javelin-behavior-aphront-basic-tokenizer' => 'b3a4b884', |     'javelin-behavior-aphront-basic-tokenizer' => 'b3a4b884', | ||||||
| @@ -567,7 +567,7 @@ return array( | |||||||
|     'javelin-behavior-conpherence-pontificate' => '21ba5861', |     'javelin-behavior-conpherence-pontificate' => '21ba5861', | ||||||
|     'javelin-behavior-conpherence-widget-pane' => '93568464', |     'javelin-behavior-conpherence-widget-pane' => '93568464', | ||||||
|     'javelin-behavior-countdown-timer' => 'e4cc26b3', |     'javelin-behavior-countdown-timer' => 'e4cc26b3', | ||||||
|     'javelin-behavior-dark-console' => '08883e8b', |     'javelin-behavior-dark-console' => 'b8df5663', | ||||||
|     'javelin-behavior-dashboard-async-panel' => '469c0d9e', |     'javelin-behavior-dashboard-async-panel' => '469c0d9e', | ||||||
|     'javelin-behavior-dashboard-move-panels' => '82439934', |     'javelin-behavior-dashboard-move-panels' => '82439934', | ||||||
|     'javelin-behavior-dashboard-query-panel-select' => '453c5375', |     'javelin-behavior-dashboard-query-panel-select' => '453c5375', | ||||||
| @@ -869,14 +869,6 @@ return array( | |||||||
|       'phabricator-shaped-request', |       'phabricator-shaped-request', | ||||||
|       'conpherence-thread-manager', |       'conpherence-thread-manager', | ||||||
|     ), |     ), | ||||||
|     '08883e8b' => array( |  | ||||||
|       'javelin-behavior', |  | ||||||
|       'javelin-stratcom', |  | ||||||
|       'javelin-util', |  | ||||||
|       'javelin-dom', |  | ||||||
|       'javelin-request', |  | ||||||
|       'phabricator-keyboard-shortcut', |  | ||||||
|     ), |  | ||||||
|     '0a3f3021' => array( |     '0a3f3021' => array( | ||||||
|       'javelin-behavior', |       'javelin-behavior', | ||||||
|       'javelin-stratcom', |       'javelin-stratcom', | ||||||
| @@ -1198,16 +1190,6 @@ return array( | |||||||
|       'javelin-vector', |       'javelin-vector', | ||||||
|       'javelin-dom', |       'javelin-dom', | ||||||
|     ), |     ), | ||||||
|     '572566ae' => array( |  | ||||||
|       'javelin-behavior', |  | ||||||
|       'javelin-request', |  | ||||||
|       'javelin-stratcom', |  | ||||||
|       'javelin-vector', |  | ||||||
|       'javelin-dom', |  | ||||||
|       'javelin-uri', |  | ||||||
|       'javelin-behavior-device', |  | ||||||
|       'phabricator-title', |  | ||||||
|     ), |  | ||||||
|     58562350 => array( |     58562350 => array( | ||||||
|       'javelin-dom', |       'javelin-dom', | ||||||
|       'javelin-util', |       'javelin-util', | ||||||
| @@ -1727,6 +1709,14 @@ return array( | |||||||
|       'javelin-dom', |       'javelin-dom', | ||||||
|       'javelin-util', |       'javelin-util', | ||||||
|     ), |     ), | ||||||
|  |     'b8df5663' => array( | ||||||
|  |       'javelin-behavior', | ||||||
|  |       'javelin-stratcom', | ||||||
|  |       'javelin-util', | ||||||
|  |       'javelin-dom', | ||||||
|  |       'javelin-request', | ||||||
|  |       'phabricator-keyboard-shortcut', | ||||||
|  |     ), | ||||||
|     'bba9eedf' => array( |     'bba9eedf' => array( | ||||||
|       'javelin-behavior', |       'javelin-behavior', | ||||||
|       'javelin-stratcom', |       'javelin-stratcom', | ||||||
| @@ -1950,6 +1940,16 @@ return array( | |||||||
|       'javelin-stratcom', |       'javelin-stratcom', | ||||||
|       'javelin-vector', |       'javelin-vector', | ||||||
|     ), |     ), | ||||||
|  |     'ee37f73a' => array( | ||||||
|  |       'javelin-behavior', | ||||||
|  |       'javelin-request', | ||||||
|  |       'javelin-stratcom', | ||||||
|  |       'javelin-vector', | ||||||
|  |       'javelin-dom', | ||||||
|  |       'javelin-uri', | ||||||
|  |       'javelin-behavior-device', | ||||||
|  |       'phabricator-title', | ||||||
|  |     ), | ||||||
|     'efe49472' => array( |     'efe49472' => array( | ||||||
|       'javelin-install', |       'javelin-install', | ||||||
|       'javelin-util', |       'javelin-util', | ||||||
|   | |||||||
| @@ -2475,6 +2475,7 @@ phutil_register_library_map(array( | |||||||
|     'PhabricatorSearchDocumentIndexer' => 'applications/search/index/PhabricatorSearchDocumentIndexer.php', |     'PhabricatorSearchDocumentIndexer' => 'applications/search/index/PhabricatorSearchDocumentIndexer.php', | ||||||
|     'PhabricatorSearchDocumentQuery' => 'applications/search/query/PhabricatorSearchDocumentQuery.php', |     'PhabricatorSearchDocumentQuery' => 'applications/search/query/PhabricatorSearchDocumentQuery.php', | ||||||
|     'PhabricatorSearchDocumentRelationship' => 'applications/search/storage/document/PhabricatorSearchDocumentRelationship.php', |     'PhabricatorSearchDocumentRelationship' => 'applications/search/storage/document/PhabricatorSearchDocumentRelationship.php', | ||||||
|  |     'PhabricatorSearchDocumentTypeDatasource' => 'applications/search/typeahead/PhabricatorSearchDocumentTypeDatasource.php', | ||||||
|     'PhabricatorSearchEditController' => 'applications/search/controller/PhabricatorSearchEditController.php', |     'PhabricatorSearchEditController' => 'applications/search/controller/PhabricatorSearchEditController.php', | ||||||
|     'PhabricatorSearchEngine' => 'applications/search/engine/PhabricatorSearchEngine.php', |     'PhabricatorSearchEngine' => 'applications/search/engine/PhabricatorSearchEngine.php', | ||||||
|     'PhabricatorSearchEngineElastic' => 'applications/search/engine/PhabricatorSearchEngineElastic.php', |     'PhabricatorSearchEngineElastic' => 'applications/search/engine/PhabricatorSearchEngineElastic.php', | ||||||
| @@ -5897,6 +5898,7 @@ phutil_register_library_map(array( | |||||||
|     'PhabricatorSearchDocumentIndexer' => 'Phobject', |     'PhabricatorSearchDocumentIndexer' => 'Phobject', | ||||||
|     'PhabricatorSearchDocumentQuery' => 'PhabricatorCursorPagedPolicyAwareQuery', |     'PhabricatorSearchDocumentQuery' => 'PhabricatorCursorPagedPolicyAwareQuery', | ||||||
|     'PhabricatorSearchDocumentRelationship' => 'PhabricatorSearchDAO', |     'PhabricatorSearchDocumentRelationship' => 'PhabricatorSearchDAO', | ||||||
|  |     'PhabricatorSearchDocumentTypeDatasource' => 'PhabricatorTypeaheadDatasource', | ||||||
|     'PhabricatorSearchEditController' => 'PhabricatorSearchBaseController', |     'PhabricatorSearchEditController' => 'PhabricatorSearchBaseController', | ||||||
|     'PhabricatorSearchEngineElastic' => 'PhabricatorSearchEngine', |     'PhabricatorSearchEngineElastic' => 'PhabricatorSearchEngine', | ||||||
|     'PhabricatorSearchEngineMySQL' => 'PhabricatorSearchEngine', |     'PhabricatorSearchEngineMySQL' => 'PhabricatorSearchEngine', | ||||||
|   | |||||||
| @@ -12,6 +12,10 @@ final class PhabricatorConpherenceThreadPHIDType extends PhabricatorPHIDType { | |||||||
|     return new ConpherenceThread(); |     return new ConpherenceThread(); | ||||||
|   } |   } | ||||||
|  |  | ||||||
|  |   public function getPHIDTypeApplicationClass() { | ||||||
|  |     return 'PhabricatorConpherenceApplication'; | ||||||
|  |   } | ||||||
|  |  | ||||||
|   protected function buildQueryForObjects( |   protected function buildQueryForObjects( | ||||||
|     PhabricatorObjectQuery $query, |     PhabricatorObjectQuery $query, | ||||||
|     array $phids) { |     array $phids) { | ||||||
|   | |||||||
| @@ -12,6 +12,10 @@ final class FundInitiativePHIDType extends PhabricatorPHIDType { | |||||||
|     return new FundInitiative(); |     return new FundInitiative(); | ||||||
|   } |   } | ||||||
|  |  | ||||||
|  |   public function getPHIDTypeApplicationClass() { | ||||||
|  |     return 'PhabricatorFundApplication'; | ||||||
|  |   } | ||||||
|  |  | ||||||
|   protected function buildQueryForObjects( |   protected function buildQueryForObjects( | ||||||
|     PhabricatorObjectQuery $query, |     PhabricatorObjectQuery $query, | ||||||
|     array $phids) { |     array $phids) { | ||||||
|   | |||||||
| @@ -26,7 +26,7 @@ final class HeraldCommitAdapter extends HeraldAdapter { | |||||||
|     return 'PhabricatorDiffusionApplication'; |     return 'PhabricatorDiffusionApplication'; | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   public function newObject() { |   protected function newObject() { | ||||||
|     return new PhabricatorRepositoryCommit(); |     return new PhabricatorRepositoryCommit(); | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   | |||||||
| @@ -24,7 +24,7 @@ final class HeraldDifferentialRevisionAdapter | |||||||
|     return 'PhabricatorDifferentialApplication'; |     return 'PhabricatorDifferentialApplication'; | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   public function newObject() { |   protected function newObject() { | ||||||
|     return new DifferentialRevision(); |     return new DifferentialRevision(); | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   | |||||||
| @@ -13,7 +13,7 @@ final class HeraldPholioMockAdapter extends HeraldAdapter { | |||||||
|     return pht('React to mocks being created or updated.'); |     return pht('React to mocks being created or updated.'); | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   public function newObject() { |   protected function newObject() { | ||||||
|     return new PholioMock(); |     return new PholioMock(); | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   | |||||||
| @@ -12,6 +12,10 @@ final class PassphraseCredentialPHIDType extends PhabricatorPHIDType { | |||||||
|     return new PassphraseCredential(); |     return new PassphraseCredential(); | ||||||
|   } |   } | ||||||
|  |  | ||||||
|  |   public function getPHIDTypeApplicationClass() { | ||||||
|  |     return 'PhabricatorPassphraseApplication'; | ||||||
|  |   } | ||||||
|  |  | ||||||
|   protected function buildQueryForObjects( |   protected function buildQueryForObjects( | ||||||
|     PhabricatorObjectQuery $query, |     PhabricatorObjectQuery $query, | ||||||
|     array $phids) { |     array $phids) { | ||||||
|   | |||||||
| @@ -31,6 +31,13 @@ abstract class PhabricatorPHIDType { | |||||||
|   } |   } | ||||||
|  |  | ||||||
|   public function getTypeIcon() { |   public function getTypeIcon() { | ||||||
|  |     // Default to the application icon if the type doesn't specify one. | ||||||
|  |     $application_class = $this->getPHIDTypeApplicationClass(); | ||||||
|  |     if ($application_class) { | ||||||
|  |       $application = newv($application_class, array()); | ||||||
|  |       return $application->getFontIcon(); | ||||||
|  |     } | ||||||
|  |  | ||||||
|     return null; |     return null; | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   | |||||||
| @@ -13,7 +13,7 @@ final class PhrictionDocumentHeraldAdapter extends HeraldAdapter { | |||||||
|     return pht('React to wiki documents being created or updated.'); |     return pht('React to wiki documents being created or updated.'); | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   public function newObject() { |   protected function newObject() { | ||||||
|     return new PhrictionDocument(); |     return new PhrictionDocument(); | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   | |||||||
| @@ -88,17 +88,11 @@ final class PhabricatorSearchApplicationSearchEngine | |||||||
|     $type_values = $saved->getParameter('types', array()); |     $type_values = $saved->getParameter('types', array()); | ||||||
|     $type_values = array_fuse($type_values); |     $type_values = array_fuse($type_values); | ||||||
|  |  | ||||||
|     $types = self::getIndexableDocumentTypes($this->requireViewer()); |     $types_control = id(new AphrontFormTokenizerControl()) | ||||||
|  |       ->setLabel(pht('Document Types')) | ||||||
|     $types_control = id(new AphrontFormCheckboxControl()) |       ->setName('types') | ||||||
|       ->setLabel(pht('Document Types')); |       ->setDatasource(new PhabricatorSearchDocumentTypeDatasource()) | ||||||
|     foreach ($types as $type => $name) { |       ->setValue($type_values); | ||||||
|       $types_control->addCheckbox( |  | ||||||
|         'types[]', |  | ||||||
|         $type, |  | ||||||
|         $name, |  | ||||||
|         isset($type_values[$type])); |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     $form |     $form | ||||||
|       ->appendChild( |       ->appendChild( | ||||||
| @@ -115,7 +109,7 @@ final class PhabricatorSearchApplicationSearchEngine | |||||||
|           ->setName('query') |           ->setName('query') | ||||||
|           ->setValue($saved->getParameter('query'))) |           ->setValue($saved->getParameter('query'))) | ||||||
|       ->appendChild($status_control) |       ->appendChild($status_control) | ||||||
|       ->appendChild($types_control) |       ->appendControl($types_control) | ||||||
|       ->appendControl( |       ->appendControl( | ||||||
|         id(new AphrontFormTokenizerControl()) |         id(new AphrontFormTokenizerControl()) | ||||||
|           ->setName('authorPHIDs') |           ->setName('authorPHIDs') | ||||||
| @@ -208,13 +202,6 @@ final class PhabricatorSearchApplicationSearchEngine | |||||||
|  |  | ||||||
|     asort($results); |     asort($results); | ||||||
|  |  | ||||||
|     // Put tasks first, see T4606. |  | ||||||
|     $results = array_select_keys( |  | ||||||
|       $results, |  | ||||||
|       array( |  | ||||||
|         ManiphestTaskPHIDType::TYPECONST, |  | ||||||
|       )) + $results; |  | ||||||
|  |  | ||||||
|     return $results; |     return $results; | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   | |||||||
| @@ -0,0 +1,56 @@ | |||||||
|  | <?php | ||||||
|  |  | ||||||
|  | final class PhabricatorSearchDocumentTypeDatasource | ||||||
|  |   extends PhabricatorTypeaheadDatasource { | ||||||
|  |  | ||||||
|  |   public function getBrowseTitle() { | ||||||
|  |     return pht('Browse Document Types'); | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   public function getPlaceholderText() { | ||||||
|  |     return pht('Select a document type...'); | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   public function getDatasourceApplicationClass() { | ||||||
|  |     return 'PhabricatorSearchApplication'; | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   public function loadResults() { | ||||||
|  |     $results = $this->buildResults(); | ||||||
|  |     return $this->filterResultsAgainstTokens($results); | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   public function renderTokens(array $values) { | ||||||
|  |     $results = $this->buildResults(); | ||||||
|  |     $results = array_select_keys($results, $values); | ||||||
|  |  | ||||||
|  |     $tokens = array(); | ||||||
|  |     foreach ($results as $result) { | ||||||
|  |       $tokens[] = PhabricatorTypeaheadTokenView::newFromTypeaheadResult( | ||||||
|  |         $result); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     return $tokens; | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   private function buildResults() { | ||||||
|  |     $types = | ||||||
|  |       PhabricatorSearchApplicationSearchEngine::getIndexableDocumentTypes(); | ||||||
|  |  | ||||||
|  |     $icons = mpull( | ||||||
|  |       PhabricatorPHIDType::getAllTypes(), | ||||||
|  |       'getTypeIcon', | ||||||
|  |       'getTypeConstant'); | ||||||
|  |  | ||||||
|  |     $results = array(); | ||||||
|  |     foreach ($types as $type => $name) { | ||||||
|  |       $results[$type] = id(new PhabricatorTypeaheadResult()) | ||||||
|  |         ->setPHID($type) | ||||||
|  |         ->setName($name) | ||||||
|  |         ->setIcon(idx($icons, $type)); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     return $results; | ||||||
|  |   } | ||||||
|  |  | ||||||
|  | } | ||||||
		Reference in New Issue
	
	Block a user
	 epriestley
					epriestley