1
0
Fork 0
mirror of https://we.phorge.it/source/phorge.git synced 2025-02-18 17:58:37 +01:00

Implement an extremely primitive typeahead browse view with offset paging

Summary:
Ref T5750. Give up and use offset paging.

Each page will become progressively slower, but the amount of time I was sinking into T7803 without making real headway was not justified by fixing this. In comparison, this took 10 minutes. It isn't really useful to browse through tens of thousands of results anyway, and no one is realistically going to try to do that (later in this sequence, I'll explicitly prevent it).

Test Plan:
This is completely primitive right now:

{F372224}

Reviewers: btrahan

Reviewed By: btrahan

Subscribers: epriestley

Maniphest Tasks: T5750

Differential Revision: https://secure.phabricator.com/D12423
This commit is contained in:
epriestley 2015-04-15 06:23:12 -07:00
parent a81072046a
commit 64182dc94d
5 changed files with 79 additions and 12 deletions

View file

@ -9,7 +9,7 @@ final class PhabricatorTypeaheadApplication extends PhabricatorApplication {
public function getRoutes() {
return array(
'/typeahead/' => array(
'class/(?:(?P<class>\w+)/)?'
'(?P<action>browse|class)/(?:(?P<class>\w+)/)?'
=> 'PhabricatorTypeaheadModularDatasourceController',
),
);

View file

@ -11,6 +11,7 @@ final class PhabricatorTypeaheadModularDatasourceController
$request = $this->getRequest();
$viewer = $request->getUser();
$query = $request->getStr('q');
$is_browse = ($request->getURIData('action') == 'browse');
// Default this to the query string to make debugging a little bit easier.
$raw_query = nonempty($request->getStr('raw'), $query);
@ -23,16 +24,11 @@ final class PhabricatorTypeaheadModularDatasourceController
->loadObjects();
if (isset($sources[$class])) {
$source = $sources[$class];
if ($source->getDatasourceApplicationClass()) {
if (!PhabricatorApplication::isClassInstalledForViewer(
$source->getDatasourceApplicationClass(),
$viewer)) {
return id(new Aphront404Response());
}
}
$source->setParameters($request->getRequestData());
// NOTE: Wrapping the source in a Composite datasource ensures we perform
// application visibility checks for the viewer, so we do not need to do
// those separately.
$composite = new PhabricatorTypeaheadRuntimeCompositeDatasource();
$composite->addDatasource($source);
@ -41,7 +37,47 @@ final class PhabricatorTypeaheadModularDatasourceController
->setQuery($query)
->setRawQuery($raw_query);
if ($is_browse) {
$limit = 3;
$offset = $request->getInt('offset');
$composite
->setLimit($limit + 1)
->setOffset($offset);
}
$results = $composite->loadResults();
if ($is_browse) {
$next_link = null;
if (count($results) > $limit) {
$results = array_slice($results, 0, $limit, $preserve_keys = true);
$next_link = phutil_tag(
'a',
array(
'href' => id(new PhutilURI($request->getRequestURI()))
->setQueryParam('offset', $offset + $limit),
),
pht('Next Page'));
}
$rows = array();
foreach ($results as $result) {
// TODO: Render nicely.
$rows[] = array_slice($result->getWireFormat(), 0, 3, true);
}
$table = id(new AphrontTableView($rows));
return $this->newDialog()
->setWidth(AphrontDialogView::WIDTH_FORM)
->setTitle(get_class($source)) // TODO: Provide nice names.
->appendChild($table)
->appendChild($next_link)
->addCancelButton('/', pht('Close'));
}
} else if ($is_browse) {
return new Aphront404Response();
} else {
$results = array();
}

View file

@ -10,17 +10,34 @@ abstract class PhabricatorTypeaheadCompositeDatasource
}
public function loadResults() {
$offset = $this->getOffset();
$limit = $this->getLimit();
$results = array();
foreach ($this->getUsableDatasources() as $source) {
$source
->setRawQuery($this->getRawQuery())
->setQuery($this->getQuery())
->setViewer($this->getViewer())
->setLimit($this->getLimit());
->setViewer($this->getViewer());
if ($limit) {
$source->setLimit($offset + $limit);
}
$results[] = $source->loadResults();
}
return array_mergev($results);
$results = array_mergev($results);
$results = msort($results, 'getName');
if ($offset || $limit) {
if (!$limit) {
$limit = count($results);
}
$results = array_slice($results, $offset, $limit, $preserve_keys = true);
}
return $results;
}
private function getUsableDatasources() {

View file

@ -5,6 +5,7 @@ abstract class PhabricatorTypeaheadDatasource extends Phobject {
private $viewer;
private $query;
private $rawQuery;
private $offset;
private $limit;
private $parameters = array();
@ -17,6 +18,15 @@ abstract class PhabricatorTypeaheadDatasource extends Phobject {
return $this->limit;
}
public function setOffset($offset) {
$this->offset = $offset;
return $this;
}
public function getOffset() {
return $this->offset;
}
public function setViewer(PhabricatorUser $viewer) {
$this->viewer = $viewer;
return $this;

View file

@ -69,6 +69,10 @@ final class PhabricatorTypeaheadResult {
return $this;
}
public function getName() {
return $this->name;
}
public function getWireFormat() {
$data = array(
$this->name,