1
0
Fork 0
mirror of https://we.phorge.it/source/phorge.git synced 2025-01-18 10:41:08 +01:00

Nearly complete lifting card-move code out of workboards

Summary: Ref T10010. This gets rid of the last dependency on the weird ColumnPositionQuery code.

Test Plan:
  - Viewed workboards.
  - Used batch editor.
  - Created a new workboard.
  - Dragged stuff around.
  - Created new tasks into columns.
  - Changed order from natural to priority, dragged things around.
  - Switched filter to custom filter, "all tasks", etc.

Reviewers: chad

Reviewed By: chad

Maniphest Tasks: T10010

Differential Revision: https://secure.phabricator.com/D15176
This commit is contained in:
epriestley 2016-02-03 11:58:14 -08:00
parent a9e98e42f5
commit e25a40236f
2 changed files with 125 additions and 148 deletions

View file

@ -28,10 +28,93 @@ final class PhabricatorProjectBoardViewController
$project = $this->getProject(); $project = $this->getProject();
$this->readRequestState(); $this->readRequestState();
$columns = $this->loadColumns($project);
// TODO: Expand the checks here if we add the ability $board_uri = $this->getApplicationURI('board/'.$project->getID().'/');
// to hide the Backlog column
$search_engine = id(new ManiphestTaskSearchEngine())
->setViewer($viewer)
->setBaseURI($board_uri)
->setIsBoardView(true);
if ($request->isFormPost() && !$request->getBool('initialize')) {
$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);
}
return id(new AphrontRedirectResponse())->setURI(
$this->getURIWithState(
$search_engine->getQueryResultsPageURI($saved->getQueryKey())));
}
$query_key = $request->getURIData('queryKey');
if (!$query_key) {
$query_key = 'open';
}
$this->queryKey = $query_key;
$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;
}
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);
}
$task_query = $search_engine->buildQueryFromSavedQuery($saved);
$tasks = $task_query
->withEdgeLogicPHIDs(
PhabricatorProjectObjectHasProjectEdgeType::EDGECONST,
PhabricatorQueryConstraint::OPERATOR_AND,
array($project->getPHID()))
->setOrder(ManiphestTaskQuery::ORDER_PRIORITY)
->setViewer($viewer)
->execute();
$tasks = mpull($tasks, null, 'getPHID');
$board_phid = $project->getPHID();
$layout_engine = id(new PhabricatorBoardLayoutEngine())
->setViewer($viewer)
->setBoardPHIDs(array($board_phid))
->setObjectPHIDs(array_keys($tasks))
->executeLayout();
$columns = $layout_engine->getColumns($board_phid);
if (!$columns) { if (!$columns) {
$can_edit = PhabricatorPolicyFilter::hasCapability( $can_edit = PhabricatorPolicyFilter::hasCapability(
$viewer, $viewer,
@ -64,124 +147,6 @@ final class PhabricatorProjectBoardViewController
->appendChild($content); ->appendChild($content);
} }
$board_uri = $this->getApplicationURI('board/'.$project->getID().'/');
$engine = id(new ManiphestTaskSearchEngine())
->setViewer($viewer)
->setBaseURI($board_uri)
->setIsBoardView(true);
if ($request->isFormPost()) {
$saved = $engine->buildSavedQueryFromRequest($request);
$engine->saveQuery($saved);
$filter_form = id(new AphrontFormView())
->setUser($viewer);
$engine->buildSearchForm($filter_form, $saved);
if ($engine->getErrors()) {
return $this->newDialog()
->setWidth(AphrontDialogView::WIDTH_FULL)
->setTitle(pht('Advanced Filter'))
->appendChild($filter_form->buildLayoutView())
->setErrors($engine->getErrors())
->setSubmitURI($board_uri)
->addSubmitButton(pht('Apply Filter'))
->addCancelButton($board_uri);
}
return id(new AphrontRedirectResponse())->setURI(
$this->getURIWithState(
$engine->getQueryResultsPageURI($saved->getQueryKey())));
}
$query_key = $request->getURIData('queryKey');
if (!$query_key) {
$query_key = 'open';
}
$this->queryKey = $query_key;
$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 ($request->getURIData('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
->withEdgeLogicPHIDs(
PhabricatorProjectObjectHasProjectEdgeType::EDGECONST,
PhabricatorQueryConstraint::OPERATOR_AND,
array($project->getPHID()))
->setOrder(ManiphestTaskQuery::ORDER_PRIORITY)
->setViewer($viewer)
->execute();
$tasks = mpull($tasks, null, 'getPHID');
if ($tasks) {
$positions = id(new PhabricatorProjectColumnPositionQuery())
->setViewer($viewer)
->withObjectPHIDs(mpull($tasks, 'getPHID'))
->withColumns($columns)
->execute();
$positions = mpull($positions, null, 'getObjectPHID');
} else {
$positions = array();
}
$task_map = array();
foreach ($tasks as $task) {
$task_phid = $task->getPHID();
if (empty($positions[$task_phid])) {
// This shouldn't normally be possible because we create positions on
// demand, but we might have raced as an object was removed from the
// board. Just drop the task if we don't have a position for it.
continue;
}
$position = $positions[$task_phid];
$task_map[$position->getColumnPHID()][] = $task_phid;
}
// If we're showing the board in "natural" order, sort columns by their
// column positions.
if ($this->sortKey == PhabricatorProjectColumn::ORDER_NATURAL) {
foreach ($task_map as $column_phid => $task_phids) {
$order = array();
foreach ($task_phids as $task_phid) {
if (isset($positions[$task_phid])) {
$order[$task_phid] = $positions[$task_phid]->getOrderingKey();
} else {
$order[$task_phid] = 0;
}
}
asort($order);
$task_map[$column_phid] = array_keys($order);
}
}
$task_can_edit_map = id(new PhabricatorPolicyFilter()) $task_can_edit_map = id(new PhabricatorPolicyFilter())
->setViewer($viewer) ->setViewer($viewer)
->requireCapabilities(array(PhabricatorPolicyCapability::CAN_EDIT)) ->requireCapabilities(array(PhabricatorPolicyCapability::CAN_EDIT))
@ -198,7 +163,10 @@ final class PhabricatorProjectBoardViewController
return new Aphront404Response(); return new Aphront404Response();
} }
$batch_task_phids = idx($task_map, $batch_column->getPHID(), array()); $batch_task_phids = $layout_engine->getColumnObjectPHIDs(
$board_phid,
$batch_column->getPHID());
foreach ($batch_task_phids as $key => $batch_task_phid) { foreach ($batch_task_phids as $key => $batch_task_phid) {
if (empty($task_can_edit_map[$batch_task_phid])) { if (empty($task_can_edit_map[$batch_task_phid])) {
unset($batch_task_phids[$key]); unset($batch_task_phids[$key]);
@ -251,9 +219,24 @@ final class PhabricatorProjectBoardViewController
$this->handles = ManiphestTaskListView::loadTaskHandles($viewer, $tasks); $this->handles = ManiphestTaskListView::loadTaskHandles($viewer, $tasks);
foreach ($columns as $column) { foreach ($columns as $column) {
$task_phids = idx($task_map, $column->getPHID(), array()); if (!$this->showHidden) {
if ($column->isHidden()) {
continue;
}
}
$task_phids = $layout_engine->getColumnObjectPHIDs(
$board_phid,
$column->getPHID());
$column_tasks = array_select_keys($tasks, $task_phids); $column_tasks = array_select_keys($tasks, $task_phids);
// If we aren't using "natural" order, reorder the column by the original
// query order.
if ($this->sortKey != PhabricatorProjectColumn::ORDER_NATURAL) {
$column_tasks = array_select_keys($column_tasks, array_keys($tasks));
}
$panel = id(new PHUIWorkpanelView()) $panel = id(new PHUIWorkpanelView())
->setHeader($column->getDisplayName()) ->setHeader($column->getDisplayName())
->setSubHeader($column->getDisplayType()) ->setSubHeader($column->getDisplayType())
@ -322,7 +305,7 @@ final class PhabricatorProjectBoardViewController
$filter_menu = $this->buildFilterMenu( $filter_menu = $this->buildFilterMenu(
$viewer, $viewer,
$custom_query, $custom_query,
$engine, $search_engine,
$query_key); $query_key);
$manage_menu = $this->buildManageMenu($project, $this->showHidden); $manage_menu = $this->buildManageMenu($project, $this->showHidden);
@ -383,25 +366,6 @@ final class PhabricatorProjectBoardViewController
$this->sortKey = $sort_key; $this->sortKey = $sort_key;
} }
private function loadColumns(PhabricatorProject $project) {
$viewer = $this->getViewer();
$column_query = id(new PhabricatorProjectColumnQuery())
->setViewer($viewer)
->withProjectPHIDs(array($project->getPHID()));
if (!$this->showHidden) {
$column_query->withStatuses(
array(PhabricatorProjectColumn::STATUS_ACTIVE));
}
$columns = $column_query->execute();
$columns = mpull($columns, null, 'getSequence');
ksort($columns);
return $columns;
}
private function buildSortMenu( private function buildSortMenu(
PhabricatorUser $viewer, PhabricatorUser $viewer,
$sort_key) { $sort_key) {
@ -797,6 +761,7 @@ final class PhabricatorProjectBoardViewController
$form = id(new AphrontFormView()) $form = id(new AphrontFormView())
->setUser($viewer) ->setUser($viewer)
->addHiddenInput('initialize', 1)
->appendRemarkupInstructions( ->appendRemarkupInstructions(
pht('The workboard for this project has not been created yet.')) pht('The workboard for this project has not been created yet.'))
->appendControl($new_selector) ->appendControl($new_selector)

View file

@ -6,7 +6,7 @@ final class PhabricatorBoardLayoutEngine extends Phobject {
private $boardPHIDs; private $boardPHIDs;
private $objectPHIDs; private $objectPHIDs;
private $boards; private $boards;
private $columnMap; private $columnMap = array();
private $objectColumnMap = array(); private $objectColumnMap = array();
private $boardLayout = array(); private $boardLayout = array();
@ -68,6 +68,17 @@ final class PhabricatorBoardLayoutEngine extends Phobject {
return $this; return $this;
} }
public function getColumns($board_phid) {
$columns = idx($this->boardLayout, $board_phid, array());
return array_select_keys($this->columnMap, array_keys($columns));
}
public function getColumnObjectPHIDs($board_phid, $column_phid) {
$columns = idx($this->boardLayout, $board_phid, array());
$positions = idx($columns, $column_phid, array());
return mpull($positions, 'getObjectPHID');
}
public function getObjectColumns($board_phid, $object_phid) { public function getObjectColumns($board_phid, $object_phid) {
$board_map = idx($this->objectColumnMap, $board_phid, array()); $board_map = idx($this->objectColumnMap, $board_phid, array());
@ -342,15 +353,16 @@ final class PhabricatorBoardLayoutEngine extends Phobject {
$board_phid = $board->getPHID(); $board_phid = $board->getPHID();
$position_groups = mgroup($positions, 'getObjectPHID'); $position_groups = mgroup($positions, 'getObjectPHID');
$layout = array();
foreach ($columns as $column) { foreach ($columns as $column) {
$column_phid = $column->getPHID();
$layout[$column_phid] = array();
if ($column->isDefaultColumn()) { if ($column->isDefaultColumn()) {
$default_phid = $column->getPHID(); $default_phid = $column_phid;
break;
} }
} }
$layout = array();
$object_phids = $this->getObjectPHIDs(); $object_phids = $this->getObjectPHIDs();
foreach ($object_phids as $object_phid) { foreach ($object_phids as $object_phid) {
$positions = idx($position_groups, $object_phid, array()); $positions = idx($position_groups, $object_phid, array());