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:
parent
ec352b1b31
commit
24b466cd62
4 changed files with 229 additions and 203 deletions
|
@ -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',
|
||||
|
|
|
@ -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/'
|
||||
|
|
|
@ -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());
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
}
|
Loading…
Reference in a new issue