1
0
Fork 0
mirror of https://we.phorge.it/source/phorge.git synced 2024-11-29 10:12:41 +01:00

Move workboard "filter" workflow to a separate controller

Summary:
Depends on D20629. Ref T4900. Currently, the "Advanced Filter..." workflow on workboards (where you build a custom query) is inline in the main board controller.

This is because the filter flow depends on some of the board view state: we want to start with the current filter applied to the board, and preserve other state after you change the filter.

Now that `ViewState` can handle state management, we can separate this stuff out pretty easily.

Test Plan:
  - Changed filters on a board.
  - Applied a custom filter to a board.
  - Changed the ordering of a board, then applied a custom filter. Verified "Cancel" and "Apply Filter" both preserve the order state.
  - Changed the ordering of a board, then applied a custom filter, intentionally making a mistake in configuring the filter by entering an invalid date. Saw a dialog with an error. After correcting the error, saw state preserved properly.

Reviewers: amckinley

Reviewed By: amckinley

Maniphest Tasks: T4900

Differential Revision: https://secure.phabricator.com/D20632
This commit is contained in:
epriestley 2019-06-30 08:04:03 -07:00
parent 9e096cd274
commit 577020aea9
7 changed files with 131 additions and 62 deletions

View file

@ -4160,6 +4160,7 @@ phutil_register_library_map(array(
'PhabricatorProjectBoardController' => 'applications/project/controller/PhabricatorProjectBoardController.php',
'PhabricatorProjectBoardDefaultController' => 'applications/project/controller/PhabricatorProjectBoardDefaultController.php',
'PhabricatorProjectBoardDisableController' => 'applications/project/controller/PhabricatorProjectBoardDisableController.php',
'PhabricatorProjectBoardFilterController' => 'applications/project/controller/PhabricatorProjectBoardFilterController.php',
'PhabricatorProjectBoardImportController' => 'applications/project/controller/PhabricatorProjectBoardImportController.php',
'PhabricatorProjectBoardManageController' => 'applications/project/controller/PhabricatorProjectBoardManageController.php',
'PhabricatorProjectBoardReorderController' => 'applications/project/controller/PhabricatorProjectBoardReorderController.php',
@ -10424,6 +10425,7 @@ phutil_register_library_map(array(
'PhabricatorProjectBoardController' => 'PhabricatorProjectController',
'PhabricatorProjectBoardDefaultController' => 'PhabricatorProjectBoardController',
'PhabricatorProjectBoardDisableController' => 'PhabricatorProjectBoardController',
'PhabricatorProjectBoardFilterController' => 'PhabricatorProjectBoardController',
'PhabricatorProjectBoardImportController' => 'PhabricatorProjectBoardController',
'PhabricatorProjectBoardManageController' => 'PhabricatorProjectBoardController',
'PhabricatorProjectBoardReorderController' => 'PhabricatorProjectBoardController',

View file

@ -66,7 +66,6 @@ final class PhabricatorProjectApplication extends PhabricatorApplication {
'subprojects/(?P<id>[1-9]\d*)/'
=> 'PhabricatorProjectSubprojectsController',
'board/(?P<id>[1-9]\d*)/'.
'(?P<filter>filter/)?'.
'(?:query/(?P<queryKey>[^/]+)/)?'
=> 'PhabricatorProjectBoardViewController',
'move/(?P<id>[1-9]\d*)/' => 'PhabricatorProjectMoveController',
@ -92,6 +91,8 @@ final class PhabricatorProjectApplication extends PhabricatorApplication {
=> 'PhabricatorProjectBoardBackgroundController',
'default/(?P<target>[^/]+)/'
=> 'PhabricatorProjectBoardDefaultController',
'filter/(?:query/(?P<queryKey>[^/]+)/)?'
=> 'PhabricatorProjectBoardFilterController',
),
'column/' => array(
'remove/(?P<id>\d+)/' =>

View file

@ -22,7 +22,7 @@ abstract class PhabricatorProjectBoardController
->readFromRequest($request);
}
final protected function newBoardDialog() {
final protected function newWorkboardDialog() {
$dialog = $this->newDialog();
$state = $this->getViewState();

View file

@ -72,7 +72,7 @@ final class PhabricatorProjectBoardDefaultController
return id(new AphrontRedirectResponse())->setURI($board_uri);
}
return $this->newBoardDialog()
return $this->newWorkboardDialog()
->setTitle($title)
->appendChild($body)
->addCancelButton($board_uri)

View file

@ -0,0 +1,56 @@
<?php
final class PhabricatorProjectBoardFilterController
extends PhabricatorProjectBoardController {
public function handleRequest(AphrontRequest $request) {
$viewer = $request->getViewer();
$response = $this->loadProject();
if ($response) {
return $response;
}
$project = $this->getProject();
$state = $this->getViewState();
$board_uri = $state->newWorkboardURI();
$search_engine = $state->getSearchEngine();
$is_submit = $request->isFormPost();
if ($is_submit) {
$saved_query = $search_engine->buildSavedQueryFromRequest($request);
$search_engine->saveQuery($saved_query);
} else {
$saved_query = $state->getSavedQuery();
if (!$saved_query) {
return new Aphront404Response();
}
}
$filter_form = id(new AphrontFormView())
->setUser($viewer);
$search_engine->buildSearchForm($filter_form, $saved_query);
$errors = $search_engine->getErrors();
if ($is_submit && !$errors) {
$query_key = $saved_query->getQueryKey();
$state->setQueryKey($query_key);
$board_uri = $state->newWorkboardURI();
return id(new AphrontRedirectResponse())->setURI($board_uri);
}
return $this->newWorkboardDialog()
->setWidth(AphrontDialogView::WIDTH_FULL)
->setTitle(pht('Advanced Filter'))
->appendChild($filter_form->buildLayoutView())
->setErrors($errors)
->addSubmitButton(pht('Apply Filter'))
->addCancelButton($board_uri);
}
}

View file

@ -21,68 +21,17 @@ final class PhabricatorProjectBoardViewController
$state = $this->getViewState();
$board_uri = $project->getWorkboardURI();
$search_engine = id(new ManiphestTaskSearchEngine())
->setViewer($viewer)
->setBaseURI($board_uri)
->setIsBoardView(true);
if ($request->isFormPost()
&& !$request->getBool('initialize')
&& !$request->getStr('move')
&& !$request->getStr('queryColumnID')) {
$saved = $search_engine->buildSavedQueryFromRequest($request);
$search_engine->saveQuery($saved);
$filter_form = id(new AphrontFormView())
->setUser($viewer);
$search_engine->buildSearchForm($filter_form, $saved);
if ($search_engine->getErrors()) {
return $this->newDialog()
->setWidth(AphrontDialogView::WIDTH_FULL)
->setTitle(pht('Advanced Filter'))
->appendChild($filter_form->buildLayoutView())
->setErrors($search_engine->getErrors())
->setSubmitURI($board_uri)
->addSubmitButton(pht('Apply Filter'))
->addCancelButton($board_uri);
}
$query_key = $saved->getQueryKey();
$results_uri = $search_engine->getQueryResultsPageURI($query_key);
$results_uri = $state->newURI($results_uri);
return id(new AphrontRedirectResponse())->setURI($results_uri);
}
$search_engine = $state->getSearchEngine();
$query_key = $state->getQueryKey();
$custom_query = null;
if ($search_engine->isBuiltinQuery($query_key)) {
$saved = $search_engine->buildSavedQueryFromBuiltin($query_key);
} else {
$saved = id(new PhabricatorSavedQueryQuery())
->setViewer($viewer)
->withQueryKeys(array($query_key))
->executeOne();
if (!$saved) {
return new Aphront404Response();
}
$custom_query = $saved;
$saved = $state->getSavedQuery();
if (!$saved) {
return new Aphront404Response();
}
if ($request->getURIData('filter')) {
$filter_form = id(new AphrontFormView())
->setUser($viewer);
$search_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);
if ($saved->getID()) {
$custom_query = $saved;
} else {
$custom_query = null;
}
$task_query = $search_engine->buildQueryFromSavedQuery($saved);

View file

@ -3,8 +3,11 @@
final class PhabricatorWorkboardViewState
extends Phobject {
private $viewer;
private $project;
private $requestState = array();
private $savedQuery;
private $searchEngine;
public function setProject(PhabricatorProject $project) {
$this->project = $project;
@ -40,9 +43,62 @@ final class PhabricatorWorkboardViewState
$this->requestState['filter'] = $request->getURIData('queryKey');
}
$this->viewer = $request->getViewer();
return $this;
}
public function getViewer() {
return $this->viewer;
}
public function getSavedQuery() {
if ($this->savedQuery === null) {
$this->savedQuery = $this->newSavedQuery();
}
return $this->savedQuery;
}
private function newSavedQuery() {
$search_engine = $this->getSearchEngine();
$query_key = $this->getQueryKey();
$viewer = $this->getViewer();
if ($search_engine->isBuiltinQuery($query_key)) {
$saved_query = $search_engine->buildSavedQueryFromBuiltin($query_key);
} else {
$saved_query = id(new PhabricatorSavedQueryQuery())
->setViewer($viewer)
->withQueryKeys(array($query_key))
->executeOne();
}
return $saved_query;
}
public function getSearchEngine() {
if ($this->searchEngine === null) {
$this->searchEngine = $this->newSearchEngine();
}
return $this->searchEngine;
}
private function newSearchEngine() {
$viewer = $this->getViewer();
// TODO: This URI is not fully state-preserving, because "SearchEngine"
// does not preserve URI parameters when constructing some URIs at time of
// writing.
$board_uri = $this->getProject()->getWorkboardURI();
return id(new ManiphestTaskSearchEngine())
->setViewer($viewer)
->setBaseURI($board_uri)
->setIsBoardView(true);
}
public function newWorkboardURI($path = null) {
$project = $this->getProject();
$uri = urisprintf('%p%p', $project->getWorkboardURI(), $path);
@ -118,6 +174,11 @@ final class PhabricatorWorkboardViewState
return $this->getDefaultQueryKey();
}
public function setQueryKey($query_key) {
$this->requestState['filter'] = $query_key;
return $this;
}
private function isValidOrder($order) {
$map = PhabricatorProjectColumnOrder::getEnabledOrders();
return isset($map[$order]);