diff --git a/src/applications/maniphest/query/ManiphestTaskSearchEngine.php b/src/applications/maniphest/query/ManiphestTaskSearchEngine.php --- a/src/applications/maniphest/query/ManiphestTaskSearchEngine.php +++ b/src/applications/maniphest/query/ManiphestTaskSearchEngine.php @@ -385,4 +385,12 @@ $saved->setParameter('projectPHIDs', $project_phids); } + protected function getNewUserHeader() { + return pht('Welcome to Maniphest'); + } + + protected function getNewUserBody() { + return pht('**Create some !!tasks!!**'); + } + } diff --git a/src/applications/search/controller/PhabricatorApplicationSearchController.php b/src/applications/search/controller/PhabricatorApplicationSearchController.php --- a/src/applications/search/controller/PhabricatorApplicationSearchController.php +++ b/src/applications/search/controller/PhabricatorApplicationSearchController.php @@ -107,11 +107,19 @@ // 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 ($pt_key != 'before' && $pt_key != 'after') { - $found_query_data = true; - break; + if (isset($exempt[$pt_key])) { + continue; } + + $found_query_data = true; + break; } } @@ -203,12 +211,15 @@ $body[] = $box; + if ($run_query) { $box->setAnchor( id(new PhabricatorAnchorView()) ->setAnchorName('R')); try { + $engine->setRequest($request); + $query = $engine->buildQueryFromSavedQuery($saved_query); $pager = $engine->newPagerForSavedQuery($saved_query); @@ -216,49 +227,58 @@ $objects = $engine->executeQuery($query, $pager); - $engine->setRequest($request); - $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))); + $force_nux = $request->getBool('nux'); + if (!$objects || $force_nux) { + $nux_view = $this->renderNewUserView($engine, $force_nux); + } else { + $nux_view = null; } - if ($list->getActions()) { - foreach ($list->getActions() as $action) { - $header->addActionLink($action); + 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->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); - } + if ($list->getActions()) { + foreach ($list->getActions() as $action) { + $header->addActionLink($action); + } + } - if ($pager->willShowPagingControls()) { - $pager_box = id(new PHUIBoxView()) - ->addPadding(PHUI::PADDING_MEDIUM) - ->addMargin(PHUI::MARGIN_LARGE) - ->setBorder(true) - ->appendChild($pager); - $body[] = $pager_box; - } + 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); + } + if ($pager->willShowPagingControls()) { + $pager_box = id(new PHUIBoxView()) + ->addPadding(PHUI::PADDING_MEDIUM) + ->addMargin(PHUI::MARGIN_LARGE) + ->setBorder(true) + ->appendChild($pager); + $body[] = $pager_box; + } + } } catch (PhabricatorTypeaheadInvalidTokenException $ex) { $errors[] = pht( 'This query specifies an invalid parameter. Review the '. @@ -396,4 +416,47 @@ 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/engine/PhabricatorApplicationSearchEngine.php b/src/applications/search/engine/PhabricatorApplicationSearchEngine.php --- a/src/applications/search/engine/PhabricatorApplicationSearchEngine.php +++ b/src/applications/search/engine/PhabricatorApplicationSearchEngine.php @@ -1354,4 +1354,28 @@ return $attachments; } + final public function renderNewUserView() { + $head = $this->getNewUserHeader(); + $body = $this->getNewUserBody(); + + if (!strlen($head) && !strlen($body)) { + return null; + } + + $viewer = $this->requireViewer(); + + return id(new PHUIBoxView()) + ->addMargin(PHUI::MARGIN_LARGE) + ->appendChild($head) + ->appendChild(new PHUIRemarkupView($viewer, $body)); + } + + protected function getNewUserHeader() { + return null; + } + + protected function getNewUserBody() { + return null; + } + }