@recaptime-dev's working patches + fork for Phorge, a community fork of Phabricator. (Upstream dev and stable branches are at upstream/main and upstream/stable respectively.) hq.recaptime.dev/wiki/Phorge
phorge phabricator
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

Improve application query UI/UX

Summary:
Ref T2625. @chad, you might have some feedback here. The behaviors this implements are:

- When the user selects "Advanced Search", we show the full search UI and no results (for performance and clarity).
- When the user submits a search which //is not// a named search, we show the full search UI and the "Save Custom Query..." button.
- When the user submits a search which //is// a named search, we show "Results for search X." with an "Edit Query..." button. The button expands the search form.
- When the user selects a builtin query (like "All Pastes"), we don't show any search UI, but I'm probably going to make this behave more like named searches.

Test Plan:
{F44346}

{F44347}

Reviewers: chad, btrahan, blc

Reviewed By: btrahan

CC: aran

Maniphest Tasks: T2625

Differential Revision: https://secure.phabricator.com/D6063

+257 -108
+46 -46
src/__celerity_resource_map__.php
··· 809 809 ), 810 810 'aphront-list-filter-view-css' => 811 811 array( 812 - 'uri' => '/res/639ea9e9/rsrc/css/aphront/list-filter-view.css', 812 + 'uri' => '/res/f754f4c5/rsrc/css/aphront/list-filter-view.css', 813 813 'type' => 'css', 814 814 'requires' => 815 815 array( ··· 3973 3973 ), array( 3974 3974 'packages' => 3975 3975 array( 3976 - 'c3ade478' => 3976 + '67ac9423' => 3977 3977 array( 3978 3978 'name' => 'core.pkg.css', 3979 3979 'symbols' => ··· 4022 4022 41 => 'phabricator-property-list-view-css', 4023 4023 42 => 'phabricator-tag-view-css', 4024 4024 ), 4025 - 'uri' => '/res/pkg/c3ade478/core.pkg.css', 4025 + 'uri' => '/res/pkg/67ac9423/core.pkg.css', 4026 4026 'type' => 'css', 4027 4027 ), 4028 4028 '98f60e3f' => ··· 4216 4216 'reverse' => 4217 4217 array( 4218 4218 'aphront-attached-file-view-css' => '6b1fccc6', 4219 - 'aphront-dialog-view-css' => 'c3ade478', 4220 - 'aphront-error-view-css' => 'c3ade478', 4221 - 'aphront-form-view-css' => 'c3ade478', 4222 - 'aphront-list-filter-view-css' => 'c3ade478', 4223 - 'aphront-pager-view-css' => 'c3ade478', 4224 - 'aphront-panel-view-css' => 'c3ade478', 4225 - 'aphront-table-view-css' => 'c3ade478', 4226 - 'aphront-tokenizer-control-css' => 'c3ade478', 4227 - 'aphront-tooltip-css' => 'c3ade478', 4228 - 'aphront-typeahead-control-css' => 'c3ade478', 4219 + 'aphront-dialog-view-css' => '67ac9423', 4220 + 'aphront-error-view-css' => '67ac9423', 4221 + 'aphront-form-view-css' => '67ac9423', 4222 + 'aphront-list-filter-view-css' => '67ac9423', 4223 + 'aphront-pager-view-css' => '67ac9423', 4224 + 'aphront-panel-view-css' => '67ac9423', 4225 + 'aphront-table-view-css' => '67ac9423', 4226 + 'aphront-tokenizer-control-css' => '67ac9423', 4227 + 'aphront-tooltip-css' => '67ac9423', 4228 + 'aphront-typeahead-control-css' => '67ac9423', 4229 4229 'differential-changeset-view-css' => 'dd27a69b', 4230 4230 'differential-core-view-css' => 'dd27a69b', 4231 4231 'differential-inline-comment-editor' => '9488bb69', ··· 4239 4239 'differential-table-of-contents-css' => 'dd27a69b', 4240 4240 'diffusion-commit-view-css' => 'c8ce2d88', 4241 4241 'diffusion-icons-css' => 'c8ce2d88', 4242 - 'global-drag-and-drop-css' => 'c3ade478', 4242 + 'global-drag-and-drop-css' => '67ac9423', 4243 4243 'inline-comment-summary-css' => 'dd27a69b', 4244 4244 'javelin-aphlict' => '98f60e3f', 4245 4245 'javelin-behavior' => 'c1359b5d', ··· 4313 4313 'javelin-util' => 'c1359b5d', 4314 4314 'javelin-vector' => 'c1359b5d', 4315 4315 'javelin-workflow' => 'c1359b5d', 4316 - 'lightbox-attachment-css' => 'c3ade478', 4316 + 'lightbox-attachment-css' => '67ac9423', 4317 4317 'maniphest-task-summary-css' => '6b1fccc6', 4318 4318 'maniphest-transaction-detail-css' => '6b1fccc6', 4319 - 'phabricator-action-list-view-css' => 'c3ade478', 4320 - 'phabricator-application-launch-view-css' => 'c3ade478', 4319 + 'phabricator-action-list-view-css' => '67ac9423', 4320 + 'phabricator-application-launch-view-css' => '67ac9423', 4321 4321 'phabricator-busy' => '98f60e3f', 4322 4322 'phabricator-content-source-view-css' => 'dd27a69b', 4323 - 'phabricator-core-buttons-css' => 'c3ade478', 4324 - 'phabricator-core-css' => 'c3ade478', 4325 - 'phabricator-crumbs-view-css' => 'c3ade478', 4326 - 'phabricator-directory-css' => 'c3ade478', 4323 + 'phabricator-core-buttons-css' => '67ac9423', 4324 + 'phabricator-core-css' => '67ac9423', 4325 + 'phabricator-crumbs-view-css' => '67ac9423', 4326 + 'phabricator-directory-css' => '67ac9423', 4327 4327 'phabricator-drag-and-drop-file-upload' => '9488bb69', 4328 4328 'phabricator-dropdown-menu' => '98f60e3f', 4329 4329 'phabricator-file-upload' => '98f60e3f', 4330 - 'phabricator-filetree-view-css' => 'c3ade478', 4331 - 'phabricator-flag-css' => 'c3ade478', 4332 - 'phabricator-form-view-css' => 'c3ade478', 4333 - 'phabricator-header-view-css' => 'c3ade478', 4330 + 'phabricator-filetree-view-css' => '67ac9423', 4331 + 'phabricator-flag-css' => '67ac9423', 4332 + 'phabricator-form-view-css' => '67ac9423', 4333 + 'phabricator-header-view-css' => '67ac9423', 4334 4334 'phabricator-hovercard' => '98f60e3f', 4335 - 'phabricator-jump-nav' => 'c3ade478', 4335 + 'phabricator-jump-nav' => '67ac9423', 4336 4336 'phabricator-keyboard-shortcut' => '98f60e3f', 4337 4337 'phabricator-keyboard-shortcut-manager' => '98f60e3f', 4338 - 'phabricator-main-menu-view' => 'c3ade478', 4338 + 'phabricator-main-menu-view' => '67ac9423', 4339 4339 'phabricator-menu-item' => '98f60e3f', 4340 - 'phabricator-nav-view-css' => 'c3ade478', 4340 + 'phabricator-nav-view-css' => '67ac9423', 4341 4341 'phabricator-notification' => '98f60e3f', 4342 - 'phabricator-notification-css' => 'c3ade478', 4343 - 'phabricator-notification-menu-css' => 'c3ade478', 4344 - 'phabricator-object-item-list-view-css' => 'c3ade478', 4342 + 'phabricator-notification-css' => '67ac9423', 4343 + 'phabricator-notification-menu-css' => '67ac9423', 4344 + 'phabricator-object-item-list-view-css' => '67ac9423', 4345 4345 'phabricator-object-selector-css' => 'dd27a69b', 4346 4346 'phabricator-phtize' => '98f60e3f', 4347 4347 'phabricator-prefab' => '98f60e3f', 4348 4348 'phabricator-project-tag-css' => '6b1fccc6', 4349 - 'phabricator-property-list-view-css' => 'c3ade478', 4350 - 'phabricator-remarkup-css' => 'c3ade478', 4349 + 'phabricator-property-list-view-css' => '67ac9423', 4350 + 'phabricator-remarkup-css' => '67ac9423', 4351 4351 'phabricator-shaped-request' => '9488bb69', 4352 - 'phabricator-side-menu-view-css' => 'c3ade478', 4353 - 'phabricator-standard-page-view' => 'c3ade478', 4354 - 'phabricator-tag-view-css' => 'c3ade478', 4352 + 'phabricator-side-menu-view-css' => '67ac9423', 4353 + 'phabricator-standard-page-view' => '67ac9423', 4354 + 'phabricator-tag-view-css' => '67ac9423', 4355 4355 'phabricator-textareautils' => '98f60e3f', 4356 4356 'phabricator-tooltip' => '98f60e3f', 4357 - 'phabricator-transaction-view-css' => 'c3ade478', 4358 - 'phabricator-zindex-css' => 'c3ade478', 4359 - 'phui-form-css' => 'c3ade478', 4360 - 'phui-icon-view-css' => 'c3ade478', 4361 - 'spacing-css' => 'c3ade478', 4362 - 'sprite-apps-large-css' => 'c3ade478', 4363 - 'sprite-gradient-css' => 'c3ade478', 4364 - 'sprite-icons-css' => 'c3ade478', 4365 - 'sprite-menu-css' => 'c3ade478', 4366 - 'syntax-highlighting-css' => 'c3ade478', 4357 + 'phabricator-transaction-view-css' => '67ac9423', 4358 + 'phabricator-zindex-css' => '67ac9423', 4359 + 'phui-form-css' => '67ac9423', 4360 + 'phui-icon-view-css' => '67ac9423', 4361 + 'spacing-css' => '67ac9423', 4362 + 'sprite-apps-large-css' => '67ac9423', 4363 + 'sprite-gradient-css' => '67ac9423', 4364 + 'sprite-icons-css' => '67ac9423', 4365 + 'sprite-menu-css' => '67ac9423', 4366 + 'syntax-highlighting-css' => '67ac9423', 4367 4367 ), 4368 4368 ));
+1 -1
src/applications/paste/controller/PhabricatorPasteController.php
··· 32 32 $nav->addFilter('savedqueries', pht('Edit Queries...')); 33 33 34 34 $nav->addLabel(pht('Search')); 35 - $nav->addFilter('filter/advanced', pht('Advanced Search')); 35 + $nav->addFilter('query/advanced', pht('Advanced Search')); 36 36 37 37 $nav->selectFilter(null); 38 38
+68 -32
src/applications/paste/controller/PhabricatorPasteListController.php
··· 27 27 28 28 $nav = $this->buildSideNavView(); 29 29 30 - if ($engine->isBuiltinQuery($this->queryKey)) { 31 - $saved_query = $engine->buildSavedQueryFromBuiltin($this->queryKey); 32 - } else { 30 + $named_query = null; 31 + $run_query = true; 32 + $query_key = $this->queryKey; 33 + if ($this->queryKey == 'advanced') { 34 + $run_query = false; 35 + $query_key = $request->getStr('query'); 36 + } 37 + 38 + if ($engine->isBuiltinQuery($query_key)) { 39 + $saved_query = $engine->buildSavedQueryFromBuiltin($query_key); 40 + $named_query = $engine->getBuiltinQuery($query_key); 41 + } else if ($query_key) { 33 42 $saved_query = id(new PhabricatorSavedQueryQuery()) 34 43 ->setViewer($user) 35 - ->withQueryKeys(array($this->queryKey)) 44 + ->withQueryKeys(array($query_key)) 36 45 ->executeOne(); 37 46 38 47 if (!$saved_query) { 39 48 return new Aphront404Response(); 40 49 } 41 - } 42 50 43 - $query = id(new PhabricatorPasteSearchEngine()) 44 - ->buildQueryFromSavedQuery($saved_query); 51 + $named_query = id(new PhabricatorNamedQueryQuery()) 52 + ->setViewer($user) 53 + ->withQueryKeys(array($saved_query->getQueryKey())) 54 + ->withEngineClassNames(array(get_class($engine))) 55 + ->withUserPHIDs(array($user->getPHID())) 56 + ->executeOne(); 57 + } else { 58 + $saved_query = $engine->buildSavedQueryFromRequest($request); 59 + } 45 60 46 61 $filter = $nav->selectFilter( 47 62 'query/'.$saved_query->getQueryKey(), 48 - 'filter/advanced'); 63 + 'query/advanced'); 49 64 50 - $pager = new AphrontCursorPagerView(); 51 - $pager->readFromRequest($request); 52 - $pastes = $query->setViewer($request->getUser()) 53 - ->needContent(true) 54 - ->executeWithCursorPager($pager); 65 + $form = id(new AphrontFormView()) 66 + ->setNoShading(true) 67 + ->setUser($user); 55 68 56 - $list = $this->buildPasteList($pastes); 57 - $list->setPager($pager); 58 - $list->setNoDataString(pht("No results found for this query.")); 69 + $engine->buildSearchForm($form, $saved_query); 59 70 60 - if ($this->queryKey !== null || $filter == "filter/advanced") { 61 - $form = id(new AphrontFormView()) 62 - ->setNoShading(true) 63 - ->setUser($user); 71 + $submit = id(new AphrontFormSubmitControl()) 72 + ->setValue(pht('Execute Query')); 64 73 65 - $engine->buildSearchForm($form, $saved_query); 74 + if ($run_query && !$named_query) { 75 + $submit->addCancelButton( 76 + '/search/edit/'.$saved_query->getQueryKey().'/', 77 + pht('Save Custom Query...')); 78 + } 66 79 67 - $submit = id(new AphrontFormSubmitControl()) 68 - ->setValue(pht('Execute Query')); 80 + $form->appendChild($submit); 81 + $filter_view = id(new AphrontListFilterView())->appendChild($form); 69 82 70 - if ($filter == 'filter/advanced') { 71 - $submit->addCancelButton( 72 - '/search/edit/'.$saved_query->getQueryKey().'/', 73 - pht('Save Custom Query...')); 83 + if ($run_query && $named_query) { 84 + if ($named_query->getIsBuiltin()) { 85 + $description = pht( 86 + 'Showing results for query "%s".', 87 + $named_query->getQueryName()); 88 + } else { 89 + $description = pht( 90 + 'Showing results for saved query "%s".', 91 + $named_query->getQueryName()); 74 92 } 75 93 76 - $form->appendChild($submit); 77 - 78 - $filter_view = id(new AphrontListFilterView())->appendChild($form); 79 - $nav->appendChild($filter_view); 94 + $filter_view->setCollapsed( 95 + pht('Edit Query...'), 96 + pht('Hide Query'), 97 + $description, 98 + $this->getApplicationURI('query/advanced/?query='.$query_key)); 80 99 } 81 100 82 - $nav->appendChild($list); 101 + $nav->appendChild($filter_view); 102 + 103 + if ($run_query) { 104 + $query = id(new PhabricatorPasteSearchEngine()) 105 + ->buildQueryFromSavedQuery($saved_query); 106 + 107 + $pager = new AphrontCursorPagerView(); 108 + $pager->readFromRequest($request); 109 + $pastes = $query->setViewer($request->getUser()) 110 + ->needContent(true) 111 + ->executeWithCursorPager($pager); 112 + 113 + $list = $this->buildPasteList($pastes); 114 + $list->setPager($pager); 115 + $list->setNoDataString(pht("No results found for this query.")); 116 + 117 + $nav->appendChild($list); 118 + } 83 119 84 120 $crumbs = $this 85 121 ->buildApplicationCrumbs($nav)
+11
src/applications/search/engine/PhabricatorApplicationSearchEngine.php
··· 107 107 /** 108 108 * @task builtin 109 109 */ 110 + public function getBuiltinQuery($query_key) { 111 + if (!$this->isBuiltinQuery($query_key)) { 112 + throw new Exception("'{$query_key}' is not a builtin!"); 113 + } 114 + return idx($this->getBuiltinQueries(), $query_key); 115 + } 116 + 117 + 118 + /** 119 + * @task builtin 120 + */ 110 121 protected function getBuiltinQueryNames() { 111 122 return array(); 112 123 }
+99 -12
src/view/layout/AphrontListFilterView.php
··· 2 2 3 3 final class AphrontListFilterView extends AphrontView { 4 4 5 - public function render() { 6 - $contents = $this->renderChildren(); 5 + private $showAction; 6 + private $hideAction; 7 + private $showHideDescription; 8 + private $showHideHref; 7 9 8 - if (!$contents) { 10 + public function setCollapsed($show, $hide, $description, $href) { 11 + $this->showAction = $show; 12 + $this->hideAction = $hide; 13 + $this->showHideDescription = $description; 14 + $this->showHideHref = $href; 15 + return $this; 16 + } 17 + 18 + public function render() { 19 + $content = $this->renderChildren(); 20 + if (!$content) { 9 21 return null; 10 22 } 11 23 12 24 require_celerity_resource('aphront-list-filter-view-css'); 13 - return hsprintf( 14 - '<div class="aphront-filter-table-wrapper">'. 15 - '<table class="aphront-list-filter-view">'. 16 - '<tr>'. 17 - '<td class="aphront-list-filter-view-controls">%s</td>'. 18 - '</tr>'. 19 - '</table>'. 20 - '</div>', 21 - $contents); 25 + 26 + $content = phutil_tag( 27 + 'div', 28 + array( 29 + 'class' => 'aphront-list-filter-view-content', 30 + ), 31 + $content); 32 + 33 + $classes = array(); 34 + $classes[] = 'aphront-list-filter-view'; 35 + if ($this->showAction !== null) { 36 + $classes[] = 'aphront-list-filter-view-collapsible'; 37 + 38 + Javelin::initBehavior('phabricator-reveal-content'); 39 + 40 + $hide_action_id = celerity_generate_unique_node_id(); 41 + $show_action_id = celerity_generate_unique_node_id(); 42 + $content_id = celerity_generate_unique_node_id(); 43 + 44 + $hide_action = javelin_tag( 45 + 'a', 46 + array( 47 + 'class' => '', 48 + 'sigil' => 'reveal-content', 49 + 'id' => $hide_action_id, 50 + 'href' => $this->showHideHref, 51 + 'meta' => array( 52 + 'hideIDs' => array($hide_action_id), 53 + 'showIDs' => array($content_id, $show_action_id), 54 + ), 55 + ), 56 + $this->showAction); 57 + 58 + $content_description = phutil_tag( 59 + 'div', 60 + array( 61 + 'class' => 'aphront-list-filter-description', 62 + ), 63 + $this->showHideDescription); 64 + 65 + $show_action = javelin_tag( 66 + 'a', 67 + array( 68 + 'class' => '', 69 + 'sigil' => 'reveal-content', 70 + 'style' => 'display: none;', 71 + 'href' => '#', 72 + 'id' => $show_action_id, 73 + 'meta' => array( 74 + 'hideIDs' => array($content_id, $show_action_id), 75 + 'showIDs' => array($hide_action_id), 76 + ), 77 + ), 78 + $this->hideAction); 79 + 80 + $reveal_block = phutil_tag( 81 + 'div', 82 + array( 83 + 'class' => 'aphront-list-filter-reveal', 84 + ), 85 + array( 86 + $content_description, 87 + $hide_action, 88 + $show_action, 89 + )); 90 + 91 + $content = array( 92 + $reveal_block, 93 + phutil_tag( 94 + 'div', 95 + array( 96 + 'id' => $content_id, 97 + 'style' => 'display: none;', 98 + ), 99 + $content), 100 + ); 101 + } 102 + 103 + return phutil_tag( 104 + 'div', 105 + array( 106 + 'class' => implode(' ', $classes), 107 + ), 108 + $content); 22 109 } 23 110 24 111 }
+32 -17
webroot/rsrc/css/aphront/list-filter-view.css
··· 2 2 * @provides aphront-list-filter-view-css 3 3 */ 4 4 5 - .aphront-filter-table-wrapper { 5 + .aphront-list-filter-view { 6 6 border-left: 1px solid #e7e7e7; 7 7 border-right: 1px solid #e7e7e7; 8 8 border-bottom: 1px solid #c0c5d1; 9 + background: #fff; 10 + 9 11 margin: 0 20px; 10 - } 11 - 12 - .device-phone .aphront-filter-table-wrapper { 13 - margin: 0; 14 12 padding: 0; 15 - background: #fff; 16 - } 17 - 18 - .aphront-list-filter-view { 19 - background: #fff; 20 - width: 100%; 21 13 box-shadow: 0 1px 2px rgba(0,0,0,0.2); 22 14 } 23 15 24 - .aphront-list-filter-view-controls { 25 - width: 100%; 16 + .device-phone .aphront-list-filter-view { 17 + margin: 0; 26 18 } 27 19 28 - .aphront-list-filter-view-controls .aphront-form-view { 20 + .aphront-list-filter-view-content .aphront-form-view { 29 21 border-left: none; 30 22 border-right: none; 31 23 padding: 12px 0 6px; 32 24 } 33 25 34 - .aphront-list-filter-view-controls .aphront-form-view .aphront-form-label { 26 + .aphront-list-filter-view-content .aphront-form-view .aphront-form-label { 35 27 width: 12%; 36 28 } 37 29 38 - .aphront-list-filter-view-controls .aphront-form-view .aphront-form-input { 30 + .aphront-list-filter-view-content .aphront-form-view .aphront-form-input { 39 31 width: 70%; 40 32 margin-left: 13%; 41 33 margin-right: 17%; 42 34 } 43 35 44 - .device-phone .aphront-list-filter-view-controls .aphront-form-view .aphront-form-input { 36 + .device-phone .aphront-list-filter-view-content .aphront-form-view 37 + .aphront-form-input { 45 38 width: 98%; 46 39 margin-left: 0%; 47 40 margin-right: 0%; 48 41 } 42 + 43 + .aphront-list-filter-view-collapsible .aphront-list-filter-view-content { 44 + border-top: 1px solid #e7e7e7; 45 + } 46 + 47 + .aphront-list-filter-reveal { 48 + margin-left: 13%; 49 + margin-right: 17%; 50 + padding: 4px; 51 + overflow: hidden; 52 + text-align: right; 53 + } 54 + 55 + .aphront-list-filter-reveal a { 56 + font-weight: bold; 57 + } 58 + 59 + .aphront-list-filter-description { 60 + margin-right: 20%; 61 + color: #666666; 62 + float: left; 63 + }