1
0
Fork 0
mirror of https://we.phorge.it/source/phorge.git synced 2024-11-10 08:52:39 +01:00

Move workboard "Move Tasks to Column..." workflow to a separate controller

Summary: Depends on D20634. Ref T4900. Ref T13316. I'm planning to do a bit of additional cleanup here in followups, but this separates the main workflow out of the common controller.

Test Plan:
  - Used "Move Tasks to Column..." to move some tasks on a board.
  - Tried to move an empty column, hit an error.

Reviewers: amckinley

Reviewed By: amckinley

Maniphest Tasks: T13316, T4900

Differential Revision: https://secure.phabricator.com/D20635
This commit is contained in:
epriestley 2019-07-02 07:39:37 -07:00
parent ec352b1b31
commit 24b466cd62
4 changed files with 229 additions and 203 deletions

View file

@ -4173,6 +4173,7 @@ phutil_register_library_map(array(
'PhabricatorProjectColumn' => 'applications/project/storage/PhabricatorProjectColumn.php',
'PhabricatorProjectColumnAuthorOrder' => 'applications/project/order/PhabricatorProjectColumnAuthorOrder.php',
'PhabricatorProjectColumnBulkEditController' => 'applications/project/controller/PhabricatorProjectColumnBulkEditController.php',
'PhabricatorProjectColumnBulkMoveController' => 'applications/project/controller/PhabricatorProjectColumnBulkMoveController.php',
'PhabricatorProjectColumnCreatedOrder' => 'applications/project/order/PhabricatorProjectColumnCreatedOrder.php',
'PhabricatorProjectColumnDetailController' => 'applications/project/controller/PhabricatorProjectColumnDetailController.php',
'PhabricatorProjectColumnEditController' => 'applications/project/controller/PhabricatorProjectColumnEditController.php',
@ -10447,6 +10448,7 @@ phutil_register_library_map(array(
),
'PhabricatorProjectColumnAuthorOrder' => 'PhabricatorProjectColumnOrder',
'PhabricatorProjectColumnBulkEditController' => 'PhabricatorProjectBoardController',
'PhabricatorProjectColumnBulkMoveController' => 'PhabricatorProjectBoardController',
'PhabricatorProjectColumnCreatedOrder' => 'PhabricatorProjectColumnOrder',
'PhabricatorProjectColumnDetailController' => 'PhabricatorProjectBoardController',
'PhabricatorProjectColumnEditController' => 'PhabricatorProjectBoardController',

View file

@ -83,6 +83,8 @@ final class PhabricatorProjectApplication extends PhabricatorApplication {
=> 'PhabricatorProjectColumnViewQueryController',
'bulk/(?P<columnID>\d+)/'
=> 'PhabricatorProjectColumnBulkEditController',
'bulkmove/(?P<columnID>\d+)/(?P<mode>project|column)/'
=> 'PhabricatorProjectColumnBulkMoveController',
'import/'
=> 'PhabricatorProjectBoardImportController',
'reorder/'

View file

@ -94,206 +94,6 @@ final class PhabricatorProjectBoardViewController
->requireCapabilities(array(PhabricatorPolicyCapability::CAN_EDIT))
->apply($tasks);
$move_id = $request->getStr('move');
if (strlen($move_id)) {
$column_id_map = mpull($columns, null, 'getID');
$move_column = idx($column_id_map, $move_id);
if (!$move_column) {
return new Aphront404Response();
}
$move_task_phids = $layout_engine->getColumnObjectPHIDs(
$board_phid,
$move_column->getPHID());
foreach ($move_task_phids as $key => $move_task_phid) {
if (empty($task_can_edit_map[$move_task_phid])) {
unset($move_task_phids[$key]);
}
}
$move_tasks = array_select_keys($tasks, $move_task_phids);
$cancel_uri = $state->newWorkboardURI();
if (!$move_tasks) {
return $this->newDialog()
->setTitle(pht('No Movable Tasks'))
->appendParagraph(
pht(
'The selected column contains no visible tasks which you '.
'have permission to move.'))
->addCancelButton($cancel_uri);
}
$move_project_phid = $project->getPHID();
$move_column_phid = null;
$move_project = null;
$move_column = null;
$columns = null;
$errors = array();
if ($request->isFormOrHiSecPost()) {
$move_project_phid = head($request->getArr('moveProjectPHID'));
if (!$move_project_phid) {
$move_project_phid = $request->getStr('moveProjectPHID');
}
if (!$move_project_phid) {
if ($request->getBool('hasProject')) {
$errors[] = pht('Choose a project to move tasks to.');
}
} else {
$target_project = id(new PhabricatorProjectQuery())
->setViewer($viewer)
->withPHIDs(array($move_project_phid))
->executeOne();
if (!$target_project) {
$errors[] = pht('You must choose a valid project.');
} else if (!$project->getHasWorkboard()) {
$errors[] = pht(
'You must choose a project with a workboard.');
} else {
$move_project = $target_project;
}
}
if ($move_project) {
$move_engine = id(new PhabricatorBoardLayoutEngine())
->setViewer($viewer)
->setBoardPHIDs(array($move_project->getPHID()))
->setFetchAllBoards(true)
->executeLayout();
$columns = $move_engine->getColumns($move_project->getPHID());
$columns = mpull($columns, null, 'getPHID');
foreach ($columns as $key => $column) {
if ($column->isHidden()) {
unset($columns[$key]);
}
}
$move_column_phid = $request->getStr('moveColumnPHID');
if (!$move_column_phid) {
if ($request->getBool('hasColumn')) {
$errors[] = pht('Choose a column to move tasks to.');
}
} else {
if (empty($columns[$move_column_phid])) {
$errors[] = pht(
'Choose a valid column on the target workboard to move '.
'tasks to.');
} else if ($columns[$move_column_phid]->getID() == $move_id) {
$errors[] = pht(
'You can not move tasks from a column to itself.');
} else {
$move_column = $columns[$move_column_phid];
}
}
}
}
if ($move_column && $move_project) {
foreach ($move_tasks as $move_task) {
$xactions = array();
// If we're switching projects, get out of the old project first
// and move to the new project.
if ($move_project->getID() != $project->getID()) {
$xactions[] = id(new ManiphestTransaction())
->setTransactionType(PhabricatorTransactions::TYPE_EDGE)
->setMetadataValue(
'edge:type',
PhabricatorProjectObjectHasProjectEdgeType::EDGECONST)
->setNewValue(
array(
'-' => array(
$project->getPHID() => $project->getPHID(),
),
'+' => array(
$move_project->getPHID() => $move_project->getPHID(),
),
));
}
$xactions[] = id(new ManiphestTransaction())
->setTransactionType(PhabricatorTransactions::TYPE_COLUMNS)
->setNewValue(
array(
array(
'columnPHID' => $move_column->getPHID(),
),
));
$editor = id(new ManiphestTransactionEditor())
->setActor($viewer)
->setContinueOnMissingFields(true)
->setContinueOnNoEffect(true)
->setContentSourceFromRequest($request)
->setCancelURI($cancel_uri);
$editor->applyTransactions($move_task, $xactions);
}
return id(new AphrontRedirectResponse())
->setURI($cancel_uri);
}
if ($move_project) {
$column_form = id(new AphrontFormView())
->setViewer($viewer)
->appendControl(
id(new AphrontFormSelectControl())
->setName('moveColumnPHID')
->setLabel(pht('Move to Column'))
->setValue($move_column_phid)
->setOptions(mpull($columns, 'getDisplayName', 'getPHID')));
return $this->newDialog()
->setTitle(pht('Move Tasks'))
->setWidth(AphrontDialogView::WIDTH_FORM)
->setErrors($errors)
->addHiddenInput('move', $move_id)
->addHiddenInput('moveProjectPHID', $move_project->getPHID())
->addHiddenInput('hasColumn', true)
->addHiddenInput('hasProject', true)
->appendParagraph(
pht(
'Choose a column on the %s workboard to move tasks to:',
$viewer->renderHandle($move_project->getPHID())))
->appendForm($column_form)
->addSubmitButton(pht('Move Tasks'))
->addCancelButton($cancel_uri);
}
if ($move_project_phid) {
$move_project_phid_value = array($move_project_phid);
} else {
$move_project_phid_value = array();
}
$project_form = id(new AphrontFormView())
->setViewer($viewer)
->appendControl(
id(new AphrontFormTokenizerControl())
->setName('moveProjectPHID')
->setLimit(1)
->setLabel(pht('Move to Project'))
->setValue($move_project_phid_value)
->setDatasource(new PhabricatorProjectDatasource()));
return $this->newDialog()
->setTitle(pht('Move Tasks'))
->setWidth(AphrontDialogView::WIDTH_FORM)
->setErrors($errors)
->addHiddenInput('move', $move_id)
->addHiddenInput('hasProject', true)
->appendForm($project_form)
->addSubmitButton(pht('Continue'))
->addCancelButton($cancel_uri);
}
$board_id = celerity_generate_unique_node_id();
$board = id(new PHUIWorkboardView())
@ -924,12 +724,15 @@ final class PhabricatorProjectBoardViewController
->setHref($bulk_edit_uri)
->setDisabled(!$can_bulk_edit);
$batch_move_uri = $request->getRequestURI();
$batch_move_uri->replaceQueryParam('move', $column->getID());
$project_move_uri = $state->newWorkboardURI(
urisprintf(
'bulkmove/%d/project/',
$column->getID()));
$column_items[] = id(new PhabricatorActionView())
->setIcon('fa-arrow-right')
->setName(pht('Move Tasks to Column...'))
->setHref($batch_move_uri)
->setHref($project_move_uri)
->setWorkflow(true);
$query_uri = urisprintf('viewquery/%d/', $column->getID());

View file

@ -0,0 +1,219 @@
<?php
final class PhabricatorProjectColumnBulkMoveController
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();
$layout_engine = $state->getLayoutEngine();
$board_phid = $project->getPHID();
$columns = $layout_engine->getColumns($board_phid);
$columns = mpull($columns, null, 'getID');
$column_id = $request->getURIData('columnID');
$move_column = idx($columns, $column_id);
if (!$move_column) {
return new Aphront404Response();
}
$move_task_phids = $layout_engine->getColumnObjectPHIDs(
$board_phid,
$move_column->getPHID());
$tasks = $state->getObjects();
$move_tasks = array_select_keys($tasks, $move_task_phids);
$move_tasks = id(new PhabricatorPolicyFilter())
->setViewer($viewer)
->requireCapabilities(array(PhabricatorPolicyCapability::CAN_EDIT))
->apply($move_tasks);
if (!$move_tasks) {
return $this->newDialog()
->setTitle(pht('No Movable Tasks'))
->appendParagraph(
pht(
'The selected column contains no visible tasks which you '.
'have permission to move.'))
->addCancelButton($board_uri);
}
$move_project_phid = $project->getPHID();
$move_column_phid = null;
$move_project = null;
$move_column = null;
$columns = null;
$errors = array();
if ($request->isFormOrHiSecPost()) {
$move_project_phid = head($request->getArr('moveProjectPHID'));
if (!$move_project_phid) {
$move_project_phid = $request->getStr('moveProjectPHID');
}
if (!$move_project_phid) {
if ($request->getBool('hasProject')) {
$errors[] = pht('Choose a project to move tasks to.');
}
} else {
$target_project = id(new PhabricatorProjectQuery())
->setViewer($viewer)
->withPHIDs(array($move_project_phid))
->executeOne();
if (!$target_project) {
$errors[] = pht('You must choose a valid project.');
} else if (!$project->getHasWorkboard()) {
$errors[] = pht(
'You must choose a project with a workboard.');
} else {
$move_project = $target_project;
}
}
if ($move_project) {
$move_engine = id(new PhabricatorBoardLayoutEngine())
->setViewer($viewer)
->setBoardPHIDs(array($move_project->getPHID()))
->setFetchAllBoards(true)
->executeLayout();
$columns = $move_engine->getColumns($move_project->getPHID());
$columns = mpull($columns, null, 'getPHID');
foreach ($columns as $key => $column) {
if ($column->isHidden()) {
unset($columns[$key]);
}
}
$move_column_phid = $request->getStr('moveColumnPHID');
if (!$move_column_phid) {
if ($request->getBool('hasColumn')) {
$errors[] = pht('Choose a column to move tasks to.');
}
} else {
if (empty($columns[$move_column_phid])) {
$errors[] = pht(
'Choose a valid column on the target workboard to move '.
'tasks to.');
} else if ($columns[$move_column_phid]->getID() == $column_id) {
$errors[] = pht(
'You can not move tasks from a column to itself.');
} else {
$move_column = $columns[$move_column_phid];
}
}
}
}
if ($move_column && $move_project) {
foreach ($move_tasks as $move_task) {
$xactions = array();
// If we're switching projects, get out of the old project first
// and move to the new project.
if ($move_project->getID() != $project->getID()) {
$xactions[] = id(new ManiphestTransaction())
->setTransactionType(PhabricatorTransactions::TYPE_EDGE)
->setMetadataValue(
'edge:type',
PhabricatorProjectObjectHasProjectEdgeType::EDGECONST)
->setNewValue(
array(
'-' => array(
$project->getPHID() => $project->getPHID(),
),
'+' => array(
$move_project->getPHID() => $move_project->getPHID(),
),
));
}
$xactions[] = id(new ManiphestTransaction())
->setTransactionType(PhabricatorTransactions::TYPE_COLUMNS)
->setNewValue(
array(
array(
'columnPHID' => $move_column->getPHID(),
),
));
$editor = id(new ManiphestTransactionEditor())
->setActor($viewer)
->setContinueOnMissingFields(true)
->setContinueOnNoEffect(true)
->setContentSourceFromRequest($request)
->setCancelURI($board_uri);
$editor->applyTransactions($move_task, $xactions);
}
return id(new AphrontRedirectResponse())
->setURI($board_uri);
}
if ($move_project) {
$column_form = id(new AphrontFormView())
->setViewer($viewer)
->appendControl(
id(new AphrontFormSelectControl())
->setName('moveColumnPHID')
->setLabel(pht('Move to Column'))
->setValue($move_column_phid)
->setOptions(mpull($columns, 'getDisplayName', 'getPHID')));
return $this->newWorkboardDialog()
->setTitle(pht('Move Tasks'))
->setWidth(AphrontDialogView::WIDTH_FORM)
->setErrors($errors)
->addHiddenInput('moveProjectPHID', $move_project->getPHID())
->addHiddenInput('hasColumn', true)
->addHiddenInput('hasProject', true)
->appendParagraph(
pht(
'Choose a column on the %s workboard to move tasks to:',
$viewer->renderHandle($move_project->getPHID())))
->appendForm($column_form)
->addSubmitButton(pht('Move Tasks'))
->addCancelButton($board_uri);
}
if ($move_project_phid) {
$move_project_phid_value = array($move_project_phid);
} else {
$move_project_phid_value = array();
}
$project_form = id(new AphrontFormView())
->setViewer($viewer)
->appendControl(
id(new AphrontFormTokenizerControl())
->setName('moveProjectPHID')
->setLimit(1)
->setLabel(pht('Move to Project'))
->setValue($move_project_phid_value)
->setDatasource(new PhabricatorProjectDatasource()));
return $this->newWorkboardDialog()
->setTitle(pht('Move Tasks'))
->setWidth(AphrontDialogView::WIDTH_FORM)
->setErrors($errors)
->addHiddenInput('hasProject', true)
->appendForm($project_form)
->addSubmitButton(pht('Continue'))
->addCancelButton($board_uri);
}
}