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:
parent
a81072046a
commit
64182dc94d
5 changed files with 79 additions and 12 deletions
|
@ -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',
|
||||
),
|
||||
);
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
|
|
@ -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() {
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -69,6 +69,10 @@ final class PhabricatorTypeaheadResult {
|
|||
return $this;
|
||||
}
|
||||
|
||||
public function getName() {
|
||||
return $this->name;
|
||||
}
|
||||
|
||||
public function getWireFormat() {
|
||||
$data = array(
|
||||
$this->name,
|
||||
|
|
Loading…
Add table
Reference in a new issue