Allow workboards to be filtered with ApplicationSearch
Summary:
Ref T4673.
IMPORTANT: I had to break one thing (see TODO) to get this working. Not sure how you want to deal with that. I might be able to put the element //inside// the workboard, or I could write some JS. But I figured I'd get feedback first.
General areas for improvement:
- It would be nice to give you some feedback that you have a filter applied.
- It would be nice to let you save and quickly select common filters.
- These would probably both be covered by a dropdown menu instead of a button, but that's more JS than I want to sign up for right now.
- Managing custom filters is also a significant amount of extra UI to build.
- Also, maybe these filters should be sticky per-board? Or across all boards? Or have a "make this my default view"? I tend to dislike implicit stickiness.
Test Plan:
Before:
{F157543}
Apply Filter:
{F157544}
Filtered:
{F157545}
Reviewers: chad, btrahan
Reviewed By: btrahan
Subscribers: qgil, swisspol, epriestley
Maniphest Tasks: T4673
Differential Revision: https://secure.phabricator.com/D9211
This commit is contained in:
@@ -5,6 +5,8 @@ final class PhabricatorProjectBoardViewController
|
||||
|
||||
private $id;
|
||||
private $handles;
|
||||
private $queryKey;
|
||||
private $filter;
|
||||
|
||||
public function shouldAllowPublic() {
|
||||
return true;
|
||||
@@ -12,6 +14,8 @@ final class PhabricatorProjectBoardViewController
|
||||
|
||||
public function willProcessRequest(array $data) {
|
||||
$this->id = $data['id'];
|
||||
$this->queryKey = idx($data, 'queryKey');
|
||||
$this->filter = (bool)idx($data, 'filter');
|
||||
}
|
||||
|
||||
public function processRequest() {
|
||||
@@ -50,12 +54,63 @@ final class PhabricatorProjectBoardViewController
|
||||
|
||||
ksort($columns);
|
||||
|
||||
$tasks = id(new ManiphestTaskQuery())
|
||||
$board_uri = $this->getApplicationURI('board/'.$project->getID().'/');
|
||||
|
||||
$engine = id(new ManiphestTaskSearchEngine())
|
||||
->setViewer($viewer)
|
||||
->withAllProjects(array($project->getPHID()))
|
||||
->withStatuses(ManiphestTaskStatus::getOpenStatusConstants())
|
||||
->setBaseURI($board_uri)
|
||||
->setIsBoardView(true);
|
||||
|
||||
if ($request->isFormPost()) {
|
||||
$saved = $engine->buildSavedQueryFromRequest($request);
|
||||
$engine->saveQuery($saved);
|
||||
return id(new AphrontRedirectResponse())->setURI(
|
||||
$engine->getQueryResultsPageURI($saved->getQueryKey()));
|
||||
}
|
||||
|
||||
$query_key = $this->queryKey;
|
||||
if (!$query_key) {
|
||||
$query_key = 'open';
|
||||
}
|
||||
|
||||
$custom_query = null;
|
||||
if ($engine->isBuiltinQuery($query_key)) {
|
||||
$saved = $engine->buildSavedQueryFromBuiltin($query_key);
|
||||
} else {
|
||||
$saved = id(new PhabricatorSavedQueryQuery())
|
||||
->setViewer($viewer)
|
||||
->withQueryKeys(array($query_key))
|
||||
->executeOne();
|
||||
|
||||
if (!$saved) {
|
||||
return new Aphront404Response();
|
||||
}
|
||||
|
||||
$custom_query = $saved;
|
||||
}
|
||||
|
||||
if ($this->filter) {
|
||||
$filter_form = id(new AphrontFormView())
|
||||
->setUser($viewer);
|
||||
$engine->buildSearchForm($filter_form, $saved);
|
||||
|
||||
return $this->newDialog()
|
||||
->setWidth(AphrontDialogView::WIDTH_FULL)
|
||||
->setTitle(pht('Advanced Filter'))
|
||||
->appendChild($filter_form->buildLayoutView())
|
||||
->setSubmitURI($board_uri)
|
||||
->addSubmitButton(pht('Apply Filter'))
|
||||
->addCancelButton($board_uri);
|
||||
}
|
||||
|
||||
$task_query = $engine->buildQueryFromSavedQuery($saved);
|
||||
|
||||
$tasks = $task_query
|
||||
->addWithAllProjects(array($project->getPHID()))
|
||||
->setOrderBy(ManiphestTaskQuery::ORDER_PRIORITY)
|
||||
->setViewer($viewer)
|
||||
->execute();
|
||||
|
||||
$tasks = mpull($tasks, null, 'getPHID');
|
||||
$task_phids = array_keys($tasks);
|
||||
|
||||
@@ -166,6 +221,87 @@ final class PhabricatorProjectBoardViewController
|
||||
->setDisabled(!$can_edit)
|
||||
->setWorkflow(!$can_edit);
|
||||
|
||||
Javelin::initBehavior(
|
||||
'boards-filter',
|
||||
array(
|
||||
));
|
||||
|
||||
$filter_icon = id(new PHUIIconView())
|
||||
->setIconFont('fa-search-plus bluegrey');
|
||||
|
||||
$named = array(
|
||||
'open' => pht('Open Tasks'),
|
||||
'all' => pht('All Tasks'),
|
||||
);
|
||||
|
||||
if ($viewer->isLoggedIn()) {
|
||||
$named['assigned'] = pht('Assigned to Me');
|
||||
}
|
||||
|
||||
if ($custom_query) {
|
||||
$named[$custom_query->getQueryKey()] = pht('Custom Filter');
|
||||
}
|
||||
|
||||
$items = array();
|
||||
foreach ($named as $key => $name) {
|
||||
$is_selected = ($key == $query_key);
|
||||
if ($is_selected) {
|
||||
$active_filter = $name;
|
||||
}
|
||||
|
||||
$is_custom = false;
|
||||
if ($custom_query) {
|
||||
$is_custom = ($key == $custom_query->getQueryKey());
|
||||
}
|
||||
|
||||
$item = id(new PhabricatorActionView())
|
||||
->setIcon('fa-search')
|
||||
->setSelected($is_selected)
|
||||
->setName($name);
|
||||
|
||||
if ($is_custom) {
|
||||
$item->setHref(
|
||||
$this->getApplicationURI(
|
||||
'board/'.$this->id.'/filter/query/'.$key.'/'));
|
||||
$item->setWorkflow(true);
|
||||
} else {
|
||||
$item->setHref($engine->getQueryResultsPageURI($key));
|
||||
}
|
||||
|
||||
$items[] = $item;
|
||||
}
|
||||
|
||||
$items[] = id(new PhabricatorActionView())
|
||||
->setIcon('fa-cog')
|
||||
->setHref($this->getApplicationURI('board/'.$this->id.'/filter/'))
|
||||
->setWorkflow(true)
|
||||
->setName(pht('Advanced Filter...'));
|
||||
|
||||
|
||||
|
||||
$filter_menu = id(new PhabricatorActionListView())
|
||||
->setUser($viewer);
|
||||
foreach ($items as $item) {
|
||||
$filter_menu->addAction($item);
|
||||
}
|
||||
|
||||
$filter_button = id(new PHUIButtonView())
|
||||
->setText(pht('Filter: %s', $active_filter))
|
||||
->setIcon($filter_icon)
|
||||
->setTag('a')
|
||||
->setHref('#')
|
||||
->addSigil('boards-filter-menu')
|
||||
|
||||
/*
|
||||
TODO: @chad, this looks really gnarly right now, at least in Safari.
|
||||
->setDropdown(true)
|
||||
*/
|
||||
|
||||
->setMetadata(
|
||||
array(
|
||||
'items' => hsprintf('%s', $filter_menu),
|
||||
));
|
||||
|
||||
$header_link = phutil_tag(
|
||||
'a',
|
||||
array(
|
||||
@@ -179,6 +315,7 @@ final class PhabricatorProjectBoardViewController
|
||||
->setNoBackground(true)
|
||||
->setImage($project->getProfileImageURI())
|
||||
->setImageURL($this->getApplicationURI('view/'.$project->getID().'/'))
|
||||
->addActionLink($filter_button)
|
||||
->addActionLink($add_button)
|
||||
->setPolicyObject($project);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user