diff --git a/src/applications/phortune/controller/PhortuneAccountListController.php b/src/applications/phortune/controller/PhortuneAccountListController.php index 4b7521ceaa..d95fd709d5 100644 --- a/src/applications/phortune/controller/PhortuneAccountListController.php +++ b/src/applications/phortune/controller/PhortuneAccountListController.php @@ -1,110 +1,110 @@ getViewer(); $accounts = id(new PhortuneAccountQuery()) ->setViewer($viewer) ->withMemberPHIDs(array($viewer->getPHID())) ->requireCapabilities( array( PhabricatorPolicyCapability::CAN_VIEW, PhabricatorPolicyCapability::CAN_EDIT, )) ->execute(); $merchants = id(new PhortuneMerchantQuery()) ->setViewer($viewer) ->withMemberPHIDs(array($viewer->getPHID())) ->execute(); $title = pht('Accounts'); $crumbs = $this->buildApplicationCrumbs(); $crumbs->addTextCrumb(pht('Accounts')); $crumbs->setBorder(true); $payment_list = id(new PHUIObjectItemListView()) ->setUser($viewer) ->setNoDataString( pht( 'You are not a member of any payment accounts. Payment '. 'accounts are used to make purchases.')); foreach ($accounts as $account) { $item = id(new PHUIObjectItemView()) ->setSubhead(pht('Account %d', $account->getID())) ->setHeader($account->getName()) ->setHref($this->getApplicationURI($account->getID().'/')) ->setObject($account) - ->setIcon('fa-credit-card'); + ->setImageIcon('fa-credit-card'); $payment_list->addItem($item); } $payment_header = id(new PHUIHeaderView()) ->setHeader(pht('Payment Accounts')) ->addActionLink( id(new PHUIButtonView()) ->setTag('a') ->setHref($this->getApplicationURI('account/edit/')) ->setIcon('fa-plus') ->setText(pht('Create Account'))); $payment_box = id(new PHUIObjectBoxView()) ->setHeader($payment_header) ->setBackground(PHUIObjectBoxView::BLUE_PROPERTY) ->setObjectList($payment_list); $merchant_list = id(new PHUIObjectItemListView()) ->setUser($viewer) ->setNoDataString( pht( 'You do not control any merchant accounts. Merchant accounts are '. 'used to receive payments.')); foreach ($merchants as $merchant) { $item = id(new PHUIObjectItemView()) ->setSubhead(pht('Merchant %d', $merchant->getID())) ->setHeader($merchant->getName()) ->setHref($this->getApplicationURI('/merchant/'.$merchant->getID().'/')) ->setObject($merchant) - ->setIcon('fa-bank'); + ->setImageIcon('fa-bank'); $merchant_list->addItem($item); } $merchant_header = id(new PHUIHeaderView()) ->setHeader(pht('Merchant Accounts')) ->addActionLink( id(new PHUIButtonView()) ->setTag('a') ->setHref($this->getApplicationURI('merchant/')) ->setIcon('fa-list') ->setText(pht('View All Merchants'))); $merchant_box = id(new PHUIObjectBoxView()) ->setHeader($merchant_header) ->setBackground(PHUIObjectBoxView::BLUE_PROPERTY) ->setObjectList($merchant_list); $header = id(new PHUIHeaderView()) ->setHeader(pht('Accounts')); $view = id(new PHUITwoColumnView()) ->setHeader($header) ->setFooter(array( $payment_box, $merchant_box, )); return $this->newPage() ->setTitle($title) ->setCrumbs($crumbs) ->appendChild($view); } } diff --git a/src/applications/phortune/controller/PhortuneProductListController.php b/src/applications/phortune/controller/PhortuneProductListController.php index eeb594d650..ee84581ae1 100644 --- a/src/applications/phortune/controller/PhortuneProductListController.php +++ b/src/applications/phortune/controller/PhortuneProductListController.php @@ -1,72 +1,72 @@ getViewer(); $pager = new AphrontCursorPagerView(); $pager->readFromRequest($request); $query = id(new PhortuneProductQuery()) ->setViewer($viewer); $products = $query->executeWithCursorPager($pager); $title = pht('Product List'); $crumbs = $this->buildApplicationCrumbs(); $crumbs->addTextCrumb( pht('Products'), $this->getApplicationURI('product/')); $crumbs->addAction( id(new PHUIListItemView()) ->setName(pht('Create Product')) ->setHref($this->getApplicationURI('product/edit/')) ->setIcon('fa-plus-square')); $crumbs->setBorder(true); $product_list = id(new PHUIObjectItemListView()) ->setUser($viewer) ->setNoDataString(pht('No products.')); foreach ($products as $product) { $view_uri = $this->getApplicationURI( 'product/view/'.$product->getID().'/'); $price = $product->getPriceAsCurrency(); $item = id(new PHUIObjectItemView()) ->setObjectName($product->getID()) ->setHeader($product->getProductName()) ->setHref($view_uri) ->addAttribute($price->formatForDisplay()) - ->setIcon('fa-gift'); + ->setImageIcon('fa-gift'); $product_list->addItem($item); } $box = id(new PHUIObjectBoxView()) ->setHeaderText(pht('Products')) ->setBackground(PHUIObjectBoxView::BLUE_PROPERTY) ->setObjectList($product_list); $header = id(new PHUIHeaderView()) ->setHeader(pht('Products')) ->setHeaderIcon('fa-gift'); $view = id(new PHUITwoColumnView()) ->setHeader($header) ->setFooter(array( $box, $pager, )); return $this->newPage() ->setTitle($title) ->setCrumbs($crumbs) ->appendChild($view); } } diff --git a/src/applications/phortune/query/PhortuneMerchantSearchEngine.php b/src/applications/phortune/query/PhortuneMerchantSearchEngine.php index 1806af371e..d37c1455b3 100644 --- a/src/applications/phortune/query/PhortuneMerchantSearchEngine.php +++ b/src/applications/phortune/query/PhortuneMerchantSearchEngine.php @@ -1,88 +1,88 @@ pht('All Merchants'), ); return $names; } public function buildSavedQueryFromBuiltin($query_key) { $query = $this->newSavedQuery(); $query->setQueryKey($query_key); switch ($query_key) { case 'all': return $query; } return parent::buildSavedQueryFromBuiltin($query_key); } protected function getRequiredHandlePHIDsForResultList( array $merchants, PhabricatorSavedQuery $query) { return array(); } protected function renderResultList( array $merchants, PhabricatorSavedQuery $query, array $handles) { assert_instances_of($merchants, 'PhortuneMerchant'); $viewer = $this->requireViewer(); $list = new PHUIObjectItemListView(); $list->setUser($viewer); foreach ($merchants as $merchant) { $item = id(new PHUIObjectItemView()) ->setSubhead(pht('Merchant %d', $merchant->getID())) ->setHeader($merchant->getName()) ->setHref('/phortune/merchant/'.$merchant->getID().'/') ->setObject($merchant) - ->setIcon('fa-bank'); + ->setImageIcon('fa-bank'); $list->addItem($item); } $result = new PhabricatorApplicationSearchResultView(); $result->setObjectList($list); $result->setNoDataString(pht('No merchants found.')); return $result; } } diff --git a/src/applications/search/controller/PhabricatorApplicationSearchController.php b/src/applications/search/controller/PhabricatorApplicationSearchController.php index 164e9aabbc..a463e50471 100644 --- a/src/applications/search/controller/PhabricatorApplicationSearchController.php +++ b/src/applications/search/controller/PhabricatorApplicationSearchController.php @@ -1,503 +1,500 @@ preface = $preface; return $this; } public function getPreface() { return $this->preface; } public function setQueryKey($query_key) { $this->queryKey = $query_key; return $this; } protected function getQueryKey() { return $this->queryKey; } public function setNavigation(AphrontSideNavFilterView $navigation) { $this->navigation = $navigation; return $this; } protected function getNavigation() { return $this->navigation; } public function setSearchEngine( PhabricatorApplicationSearchEngine $search_engine) { $this->searchEngine = $search_engine; return $this; } protected function getSearchEngine() { return $this->searchEngine; } protected function validateDelegatingController() { $parent = $this->getDelegatingController(); if (!$parent) { throw new Exception( pht('You must delegate to this controller, not invoke it directly.')); } $engine = $this->getSearchEngine(); if (!$engine) { throw new PhutilInvalidStateException('setEngine'); } $engine->setViewer($this->getRequest()->getUser()); $parent = $this->getDelegatingController(); } public function processRequest() { $this->validateDelegatingController(); $key = $this->getQueryKey(); if ($key == 'edit') { return $this->processEditRequest(); } else { return $this->processSearchRequest(); } } private function processSearchRequest() { $parent = $this->getDelegatingController(); $request = $this->getRequest(); $user = $request->getUser(); $engine = $this->getSearchEngine(); $nav = $this->getNavigation(); if (!$nav) { $nav = $this->buildNavigation(); } if ($request->isFormPost()) { $saved_query = $engine->buildSavedQueryFromRequest($request); $engine->saveQuery($saved_query); return id(new AphrontRedirectResponse())->setURI( $engine->getQueryResultsPageURI($saved_query->getQueryKey()).'#R'); } $named_query = null; $run_query = true; $query_key = $this->queryKey; if ($this->queryKey == 'advanced') { $run_query = false; $query_key = $request->getStr('query'); } else if (!strlen($this->queryKey)) { $found_query_data = false; if ($request->isHTTPGet() || $request->isQuicksand()) { // If this is a GET request and it has some query data, don't // do anything unless it's only before= or after=. We'll build and // execute a query from it below. This allows external tools to build // URIs like "/query/?users=a,b". $pt_data = $request->getPassthroughRequestData(); $exempt = array( 'before' => true, 'after' => true, 'nux' => true, ); foreach ($pt_data as $pt_key => $pt_value) { if (isset($exempt[$pt_key])) { continue; } $found_query_data = true; break; } } if (!$found_query_data) { // Otherwise, there's no query data so just run the user's default // query for this application. $query_key = head_key($engine->loadEnabledNamedQueries()); } } if ($engine->isBuiltinQuery($query_key)) { $saved_query = $engine->buildSavedQueryFromBuiltin($query_key); $named_query = idx($engine->loadEnabledNamedQueries(), $query_key); } else if ($query_key) { $saved_query = id(new PhabricatorSavedQueryQuery()) ->setViewer($user) ->withQueryKeys(array($query_key)) ->executeOne(); if (!$saved_query) { return new Aphront404Response(); } $named_query = idx($engine->loadEnabledNamedQueries(), $query_key); } else { $saved_query = $engine->buildSavedQueryFromRequest($request); // Save the query to generate a query key, so "Save Custom Query..." and // other features like Maniphest's "Export..." work correctly. $engine->saveQuery($saved_query); } $nav->selectFilter( 'query/'.$saved_query->getQueryKey(), 'query/advanced'); $form = id(new AphrontFormView()) ->setUser($user) ->setAction($request->getPath()); $engine->buildSearchForm($form, $saved_query); $errors = $engine->getErrors(); if ($errors) { $run_query = false; } $submit = id(new AphrontFormSubmitControl()) ->setValue(pht('Execute Query')); if ($run_query && !$named_query && $user->isLoggedIn()) { $submit->addCancelButton( '/search/edit/'.$saved_query->getQueryKey().'/', pht('Save Custom Query...')); } // TODO: A "Create Dashboard Panel" action goes here somewhere once // we sort out T5307. $form->appendChild($submit); $body = array(); if ($this->getPreface()) { $body[] = $this->getPreface(); } if ($named_query) { $title = $named_query->getQueryName(); } else { $title = pht('Advanced Search'); } $header = id(new PHUIHeaderView()) ->setHeader($title) ->setProfileHeader(true); $box = id(new PHUIObjectBoxView()) ->setHeader($header) ->addClass('application-search-results'); if ($run_query || $named_query) { $box->setShowHide( pht('Edit Query'), pht('Hide Query'), $form, $this->getApplicationURI('query/advanced/?query='.$query_key), (!$named_query ? true : false)); } else { $box->setForm($form); } $body[] = $box; $more_crumbs = null; if ($run_query) { $exec_errors = array(); $box->setAnchor( id(new PhabricatorAnchorView()) ->setAnchorName('R')); try { $engine->setRequest($request); $query = $engine->buildQueryFromSavedQuery($saved_query); $pager = $engine->newPagerForSavedQuery($saved_query); $pager->readFromRequest($request); $objects = $engine->executeQuery($query, $pager); $force_nux = $request->getBool('nux'); if (!$objects || $force_nux) { $nux_view = $this->renderNewUserView($engine, $force_nux); } else { $nux_view = null; } if ($nux_view) { $box->appendChild($nux_view); } else { $list = $engine->renderResults($objects, $saved_query); if (!($list instanceof PhabricatorApplicationSearchResultView)) { throw new Exception( pht( 'SearchEngines must render a "%s" object, but this engine '. '(of class "%s") rendered something else.', 'PhabricatorApplicationSearchResultView', get_class($engine))); } if ($list->getActions()) { foreach ($list->getActions() as $action) { $header->addActionLink($action); } } if ($list->getObjectList()) { $box->setObjectList($list->getObjectList()); } if ($list->getTable()) { $box->setTable($list->getTable()); } if ($list->getInfoView()) { $box->setInfoView($list->getInfoView()); } if ($list->getContent()) { $box->appendChild($list->getContent()); } - if ($list->getCollapsed()) { - $box->setCollapsed(true); - } $result_header = $list->getHeader(); if ($result_header) { $box->setHeader($result_header); } $more_crumbs = $list->getCrumbs(); if ($pager->willShowPagingControls()) { $pager_box = id(new PHUIBoxView()) ->setColor(PHUIBoxView::GREY) ->addClass('application-search-pager') ->appendChild($pager); $body[] = $pager_box; } } } catch (PhabricatorTypeaheadInvalidTokenException $ex) { $exec_errors[] = pht( 'This query specifies an invalid parameter. Review the '. 'query parameters and correct errors.'); } // The engine may have encountered additional errors during rendering; // merge them in and show everything. foreach ($engine->getErrors() as $error) { $exec_errors[] = $error; } $errors = $exec_errors; } if ($errors) { $box->setFormErrors($errors, pht('Query Errors')); } $crumbs = $parent ->buildApplicationCrumbs() ->setBorder(true); if ($more_crumbs) { $query_uri = $engine->getQueryResultsPageURI($saved_query->getQueryKey()); $crumbs->addTextCrumb($title, $query_uri); foreach ($more_crumbs as $crumb) { $crumbs->addCrumb($crumb); } } else { $crumbs->addTextCrumb($title); } require_celerity_resource('application-search-view-css'); return $this->newPage() ->setApplicationMenu($this->buildApplicationMenu()) ->setTitle(pht('Query: %s', $title)) ->setCrumbs($crumbs) ->setNavigation($nav) ->appendChild($body) ->addClass('application-search-view'); } private function processEditRequest() { $parent = $this->getDelegatingController(); $request = $this->getRequest(); $user = $request->getUser(); $engine = $this->getSearchEngine(); $nav = $this->getNavigation(); if (!$nav) { $nav = $this->buildNavigation(); } $named_queries = $engine->loadAllNamedQueries(); $list_id = celerity_generate_unique_node_id(); $list = new PHUIObjectItemListView(); $list->setUser($user); $list->setID($list_id); Javelin::initBehavior( 'search-reorder-queries', array( 'listID' => $list_id, 'orderURI' => '/search/order/'.get_class($engine).'/', )); foreach ($named_queries as $named_query) { $class = get_class($engine); $key = $named_query->getQueryKey(); $item = id(new PHUIObjectItemView()) ->setHeader($named_query->getQueryName()) ->setHref($engine->getQueryResultsPageURI($key)); if ($named_query->getIsBuiltin() && $named_query->getIsDisabled()) { $icon = 'fa-plus'; } else { $icon = 'fa-times'; } $item->addAction( id(new PHUIListItemView()) ->setIcon($icon) ->setHref('/search/delete/'.$key.'/'.$class.'/') ->setWorkflow(true)); if ($named_query->getIsBuiltin()) { if ($named_query->getIsDisabled()) { $item->addIcon('fa-times lightgreytext', pht('Disabled')); $item->setDisabled(true); } else { $item->addIcon('fa-lock lightgreytext', pht('Builtin')); } } else { $item->addAction( id(new PHUIListItemView()) ->setIcon('fa-pencil') ->setHref('/search/edit/'.$key.'/')); } $item->setGrippable(true); $item->addSigil('named-query'); $item->setMetadata( array( 'queryKey' => $named_query->getQueryKey(), )); $list->addItem($item); } $list->setNoDataString(pht('No saved queries.')); $crumbs = $parent ->buildApplicationCrumbs() ->addTextCrumb(pht('Saved Queries'), $engine->getQueryManagementURI()) ->setBorder(true); $nav->selectFilter('query/edit'); $header = id(new PHUIHeaderView()) ->setHeader(pht('Saved Queries')) ->setProfileHeader(true); $box = id(new PHUIObjectBoxView()) ->setHeader($header) ->setObjectList($list) ->addClass('application-search-results'); require_celerity_resource('application-search-view-css'); return $this->newPage() ->setApplicationMenu($this->buildApplicationMenu()) ->setTitle(pht('Saved Queries')) ->setCrumbs($crumbs) ->setNavigation($nav) ->addClass('application-search-view') ->appendChild($box); } public function buildApplicationMenu() { $menu = $this->getDelegatingController() ->buildApplicationMenu(); if ($menu instanceof PHUIApplicationMenuView) { $menu->setSearchEngine($this->getSearchEngine()); } return $menu; } private function buildNavigation() { $viewer = $this->getViewer(); $engine = $this->getSearchEngine(); $nav = id(new AphrontSideNavFilterView()) ->setUser($viewer) ->setBaseURI(new PhutilURI($this->getApplicationURI())); $engine->addNavigationItems($nav->getMenu()); return $nav; } private function renderNewUserView( PhabricatorApplicationSearchEngine $engine, $force_nux) { // Don't render NUX if the user has clicked away from the default page. if (strlen($this->getQueryKey())) { return null; } // Don't put NUX in panels because it would be weird. if ($engine->isPanelContext()) { return null; } // Try to render the view itself first, since this should be very cheap // (just returning some text). $nux_view = $engine->renderNewUserView(); if (!$nux_view) { return null; } $query = $engine->newQuery(); if (!$query) { return null; } // Try to load any object at all. If we can, the application has seen some // use so we just render the normal view. if (!$force_nux) { $object = $query ->setViewer(PhabricatorUser::getOmnipotentUser()) ->setLimit(1) ->execute(); if ($object) { return null; } } return $nux_view; } } diff --git a/src/applications/search/view/PhabricatorApplicationSearchResultView.php b/src/applications/search/view/PhabricatorApplicationSearchResultView.php index 5bcfdcf675..1c3f4aad65 100644 --- a/src/applications/search/view/PhabricatorApplicationSearchResultView.php +++ b/src/applications/search/view/PhabricatorApplicationSearchResultView.php @@ -1,109 +1,99 @@ objectList = $list; return $this; } public function getObjectList() { $list = $this->objectList; if ($list) { if ($this->noDataString) { $list->setNoDataString($this->noDataString); } else { $list->setNoDataString(pht('No results found for this query.')); } } return $list; } public function setTable($table) { $this->table = $table; return $this; } public function getTable() { return $this->table; } public function setInfoView(PHUIInfoView $infoview) { $this->infoView = $infoview; return $this; } public function getInfoView() { return $this->infoView; } public function setContent($content) { $this->content = $content; return $this; } public function getContent() { return $this->content; } public function addAction(PHUIButtonView $button) { $this->actions[] = $button; return $this; } public function getActions() { return $this->actions; } - public function setCollapsed($collapsed) { - $this->collapsed = $collapsed; - return $this; - } - - public function getCollapsed() { - return $this->collapsed; - } - public function setNoDataString($nodata) { $this->noDataString = $nodata; return $this; } public function setCrumbs(array $crumbs) { assert_instances_of($crumbs, 'PHUICrumbView'); $this->crumbs = $crumbs; return $this; } public function getCrumbs() { return $this->crumbs; } public function setHeader(PHUIHeaderView $header) { $this->header = $header; return $this; } public function getHeader() { return $this->header; } } diff --git a/webroot/rsrc/css/application/search/application-search-view.css b/webroot/rsrc/css/application/search/application-search-view.css index 24ee18c847..4a573f5111 100644 --- a/webroot/rsrc/css/application/search/application-search-view.css +++ b/webroot/rsrc/css/application/search/application-search-view.css @@ -1,50 +1,55 @@ /** * @provides application-search-view-css */ .application-search-view { background-color: #fff; } .application-search-view .application-search-results.phui-object-box { margin: 0; padding: 0 16px 24px; } .application-search-view .application-search-results .phui-profile-header { padding: 16px 8px; border-bottom: 1px solid {$thinblueborder}; } +.application-search-view .phui-object-box.phui-object-box-collapsed + .phui-header-shell { + padding: 20px 8px; +} + .application-search-results .phui-profile-header.phui-header-shell .phui-header-header { font-size: 20px; } .device-phone.application-search-view .application-search-results .phui-profile-header { padding: 12px 0; } .device-phone .application-search-results .phui-profile-header.phui-header-shell .phui-header-header { font-size: 16px; } .device-phone.application-search-view .application-search-results.phui-object-box { padding: 0 12px; } .application-search-view .phui-box-border { border: none; } .application-search-pager { margin: 0 16px 16px 16px; padding: 8px; } .device-phone .application-search-pager { margin: 12px; }