mirror of
https://we.phorge.it/source/phorge.git
synced 2024-11-10 00:42:41 +01:00
Make tokenizer browse view paging work correctly
Summary: Ref T5750. Adds a working "more results". Hard limits at 1000 results to mitigate the amount of trouble offset paging can get us into. Test Plan: Artificially set hard limit down; clicked through results. {F372284} {F372285} Reviewers: chad, btrahan Reviewed By: btrahan Subscribers: epriestley Maniphest Tasks: T5750 Differential Revision: https://secure.phabricator.com/D12425
This commit is contained in:
parent
6a4de406b8
commit
06d79703d6
3 changed files with 121 additions and 9 deletions
|
@ -37,9 +37,18 @@ final class PhabricatorTypeaheadModularDatasourceController
|
|||
->setQuery($query)
|
||||
->setRawQuery($raw_query);
|
||||
|
||||
$hard_limit = 1000;
|
||||
|
||||
if ($is_browse) {
|
||||
$limit = 10;
|
||||
$offset = $request->getInt('offset');
|
||||
|
||||
if (($offset + $limit) >= $hard_limit) {
|
||||
// Offset-based paging is intrinsically slow; hard-cap how far we're
|
||||
// willing to go with it.
|
||||
return new Aphront404Response();
|
||||
}
|
||||
|
||||
$composite
|
||||
->setLimit($limit + 1)
|
||||
->setOffset($offset);
|
||||
|
@ -49,15 +58,32 @@ final class PhabricatorTypeaheadModularDatasourceController
|
|||
|
||||
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'));
|
||||
if (($offset + (2 * $limit)) < $hard_limit) {
|
||||
$next_uri = id(new PhutilURI($request->getRequestURI()))
|
||||
->setQueryParam('offset', $offset + $limit);
|
||||
|
||||
$next_link = javelin_tag(
|
||||
'a',
|
||||
array(
|
||||
'href' => $next_uri,
|
||||
'class' => 'typeahead-browse-more',
|
||||
'sigil' => 'typeahead-browse-more',
|
||||
'mustcapture' => true,
|
||||
),
|
||||
pht('More Results'));
|
||||
} else {
|
||||
// If the user has paged through more than 1K results, don't
|
||||
// offer to page any further.
|
||||
$next_link = javelin_tag(
|
||||
'div',
|
||||
array(
|
||||
'class' => 'typeahead-browse-hard-limit',
|
||||
),
|
||||
pht('You reach the edge of the abyss.'));
|
||||
}
|
||||
}
|
||||
|
||||
$items = array();
|
||||
|
@ -72,11 +98,32 @@ final class PhabricatorTypeaheadModularDatasourceController
|
|||
$token);
|
||||
}
|
||||
|
||||
$markup = array(
|
||||
$items,
|
||||
$next_link,
|
||||
);
|
||||
|
||||
if ($request->isAjax()) {
|
||||
$content = array(
|
||||
'markup' => hsprintf('%s', $markup),
|
||||
);
|
||||
return id(new AphrontAjaxResponse())->setContent($content);
|
||||
}
|
||||
|
||||
$this->requireResource('typeahead-browse-css');
|
||||
$this->initBehavior('typeahead-browse');
|
||||
|
||||
$markup = phutil_tag(
|
||||
'div',
|
||||
array(
|
||||
'class' => 'typeahead-browse-frame',
|
||||
),
|
||||
$markup);
|
||||
|
||||
return $this->newDialog()
|
||||
->setWidth(AphrontDialogView::WIDTH_FORM)
|
||||
->setTitle(get_class($source)) // TODO: Provide nice names.
|
||||
->appendChild($items)
|
||||
->appendChild($next_link)
|
||||
->appendChild($markup)
|
||||
->addCancelButton('/', pht('Close'));
|
||||
}
|
||||
|
||||
|
|
34
webroot/rsrc/css/aphront/typeahead-browse.css
Normal file
34
webroot/rsrc/css/aphront/typeahead-browse.css
Normal file
|
@ -0,0 +1,34 @@
|
|||
/**
|
||||
* @provides typeahead-browse-css
|
||||
*/
|
||||
|
||||
.typeahead-browse-more,
|
||||
.typeahead-browse-hard-limit {
|
||||
display: block;
|
||||
padding: 8px;
|
||||
margin: 8px 0 0;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.typeahead-browse-more {
|
||||
background: {$lightblue};
|
||||
border: 1px solid {$lightblueborder};
|
||||
}
|
||||
|
||||
.typeahead-browse-more.loading {
|
||||
opacity: 0.8;
|
||||
}
|
||||
|
||||
.typeahead-browse-hard-limit {
|
||||
background: {$lightgreybackground};
|
||||
border: 1px solid {$lightgreyborder};
|
||||
color: {$lightgreytext};
|
||||
}
|
||||
|
||||
.typeahead-browse-frame {
|
||||
overflow-x: hidden;
|
||||
overflow-y: auto;
|
||||
padding: 4px;
|
||||
height: 260px;
|
||||
border: 1px solid {$lightgreyborder};
|
||||
}
|
|
@ -0,0 +1,31 @@
|
|||
/**
|
||||
* @provides javelin-behavior-typeahead-browse
|
||||
* @requires javelin-behavior
|
||||
* javelin-stratcom
|
||||
* javelin-workflow
|
||||
* javelin-dom
|
||||
*/
|
||||
|
||||
JX.behavior('typeahead-browse', function() {
|
||||
var loading = false;
|
||||
|
||||
JX.Stratcom.listen('click', 'typeahead-browse-more', function(e) {
|
||||
e.kill();
|
||||
|
||||
if (loading) {
|
||||
return;
|
||||
}
|
||||
var link = e.getTarget();
|
||||
|
||||
loading = true;
|
||||
JX.DOM.alterClass(link, 'loading', true);
|
||||
|
||||
JX.Workflow.newFromLink(link)
|
||||
.setHandler(function(r) {
|
||||
loading = false;
|
||||
JX.DOM.replace(link, JX.$H(r.markup));
|
||||
})
|
||||
.start();
|
||||
});
|
||||
|
||||
});
|
Loading…
Reference in a new issue