mirror of
https://we.phorge.it/source/phorge.git
synced 2024-12-19 12:00:55 +01:00
Allow workboards to be disabled, hiding "(Backlog)" column annotations
Summary: Fixes T7410. - Adds a "Disable Workboard" action to the "Manage Backlog" menu. - We'll probably move this somewhere else if/when that column gets too messy. - Disabling a board hides it, prevents it from being recreated by non-editors, and hides the "Project (Backlog)" annotations. - Resotring a board puts it back in pristine condition. Test Plan: - Disabled a board. - Verified "(Backlog)" annotations vanished. - Enabled a board. Reviewers: chad Reviewed By: chad Subscribers: mbishopim3 Maniphest Tasks: T7410 Differential Revision: https://secure.phabricator.com/D15215
This commit is contained in:
parent
9c95b387bd
commit
3682cc9bb2
7 changed files with 201 additions and 9 deletions
|
@ -2860,6 +2860,7 @@ phutil_register_library_map(array(
|
||||||
'PhabricatorProjectApplication' => 'applications/project/application/PhabricatorProjectApplication.php',
|
'PhabricatorProjectApplication' => 'applications/project/application/PhabricatorProjectApplication.php',
|
||||||
'PhabricatorProjectArchiveController' => 'applications/project/controller/PhabricatorProjectArchiveController.php',
|
'PhabricatorProjectArchiveController' => 'applications/project/controller/PhabricatorProjectArchiveController.php',
|
||||||
'PhabricatorProjectBoardController' => 'applications/project/controller/PhabricatorProjectBoardController.php',
|
'PhabricatorProjectBoardController' => 'applications/project/controller/PhabricatorProjectBoardController.php',
|
||||||
|
'PhabricatorProjectBoardDisableController' => 'applications/project/controller/PhabricatorProjectBoardDisableController.php',
|
||||||
'PhabricatorProjectBoardImportController' => 'applications/project/controller/PhabricatorProjectBoardImportController.php',
|
'PhabricatorProjectBoardImportController' => 'applications/project/controller/PhabricatorProjectBoardImportController.php',
|
||||||
'PhabricatorProjectBoardReorderController' => 'applications/project/controller/PhabricatorProjectBoardReorderController.php',
|
'PhabricatorProjectBoardReorderController' => 'applications/project/controller/PhabricatorProjectBoardReorderController.php',
|
||||||
'PhabricatorProjectBoardViewController' => 'applications/project/controller/PhabricatorProjectBoardViewController.php',
|
'PhabricatorProjectBoardViewController' => 'applications/project/controller/PhabricatorProjectBoardViewController.php',
|
||||||
|
@ -7274,6 +7275,7 @@ phutil_register_library_map(array(
|
||||||
'PhabricatorProjectApplication' => 'PhabricatorApplication',
|
'PhabricatorProjectApplication' => 'PhabricatorApplication',
|
||||||
'PhabricatorProjectArchiveController' => 'PhabricatorProjectController',
|
'PhabricatorProjectArchiveController' => 'PhabricatorProjectController',
|
||||||
'PhabricatorProjectBoardController' => 'PhabricatorProjectController',
|
'PhabricatorProjectBoardController' => 'PhabricatorProjectController',
|
||||||
|
'PhabricatorProjectBoardDisableController' => 'PhabricatorProjectBoardController',
|
||||||
'PhabricatorProjectBoardImportController' => 'PhabricatorProjectBoardController',
|
'PhabricatorProjectBoardImportController' => 'PhabricatorProjectBoardController',
|
||||||
'PhabricatorProjectBoardReorderController' => 'PhabricatorProjectBoardController',
|
'PhabricatorProjectBoardReorderController' => 'PhabricatorProjectBoardController',
|
||||||
'PhabricatorProjectBoardViewController' => 'PhabricatorProjectBoardController',
|
'PhabricatorProjectBoardViewController' => 'PhabricatorProjectBoardController',
|
||||||
|
|
|
@ -84,6 +84,8 @@ final class PhabricatorProjectApplication extends PhabricatorApplication {
|
||||||
=> 'PhabricatorProjectBoardImportController',
|
=> 'PhabricatorProjectBoardImportController',
|
||||||
'reorder/'
|
'reorder/'
|
||||||
=> 'PhabricatorProjectBoardReorderController',
|
=> 'PhabricatorProjectBoardReorderController',
|
||||||
|
'disable/'
|
||||||
|
=> 'PhabricatorProjectBoardDisableController',
|
||||||
),
|
),
|
||||||
'update/(?P<id>[1-9]\d*)/(?P<action>[^/]+)/'
|
'update/(?P<id>[1-9]\d*)/(?P<action>[^/]+)/'
|
||||||
=> 'PhabricatorProjectUpdateController',
|
=> 'PhabricatorProjectUpdateController',
|
||||||
|
|
|
@ -0,0 +1,61 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
final class PhabricatorProjectBoardDisableController
|
||||||
|
extends PhabricatorProjectBoardController {
|
||||||
|
|
||||||
|
public function handleRequest(AphrontRequest $request) {
|
||||||
|
$viewer = $request->getUser();
|
||||||
|
$project_id = $request->getURIData('projectID');
|
||||||
|
|
||||||
|
$project = id(new PhabricatorProjectQuery())
|
||||||
|
->setViewer($viewer)
|
||||||
|
->requireCapabilities(
|
||||||
|
array(
|
||||||
|
PhabricatorPolicyCapability::CAN_VIEW,
|
||||||
|
PhabricatorPolicyCapability::CAN_EDIT,
|
||||||
|
))
|
||||||
|
->withIDs(array($project_id))
|
||||||
|
->executeOne();
|
||||||
|
if (!$project) {
|
||||||
|
return new Aphront404Response();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!$project->getHasWorkboard()) {
|
||||||
|
return new Aphront404Response();
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->setProject($project);
|
||||||
|
$id = $project->getID();
|
||||||
|
|
||||||
|
$board_uri = $this->getApplicationURI("board/{$id}/");
|
||||||
|
|
||||||
|
if ($request->isFormPost()) {
|
||||||
|
$xactions = array();
|
||||||
|
|
||||||
|
$xactions[] = id(new PhabricatorProjectTransaction())
|
||||||
|
->setTransactionType(PhabricatorProjectTransaction::TYPE_HASWORKBOARD)
|
||||||
|
->setNewValue(0);
|
||||||
|
|
||||||
|
id(new PhabricatorProjectTransactionEditor())
|
||||||
|
->setActor($viewer)
|
||||||
|
->setContentSourceFromRequest($request)
|
||||||
|
->setContinueOnNoEffect(true)
|
||||||
|
->setContinueOnMissingFields(true)
|
||||||
|
->applyTransactions($project, $xactions);
|
||||||
|
|
||||||
|
return id(new AphrontRedirectResponse())
|
||||||
|
->setURI($board_uri);
|
||||||
|
}
|
||||||
|
|
||||||
|
return $this->newDialog()
|
||||||
|
->setTitle(pht('Disable Workboard'))
|
||||||
|
->appendParagraph(
|
||||||
|
pht(
|
||||||
|
'Disabling a workboard hides the board. Objects on the board '.
|
||||||
|
'will no longer be annotated with column names in other '.
|
||||||
|
'applications. You can restore the workboard later.'))
|
||||||
|
->addCancelButton($board_uri)
|
||||||
|
->addSubmitButton(pht('Disable Workboard'));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -121,19 +121,28 @@ final class PhabricatorProjectBoardViewController
|
||||||
->setViewer($viewer)
|
->setViewer($viewer)
|
||||||
->setBoardPHIDs(array($board_phid))
|
->setBoardPHIDs(array($board_phid))
|
||||||
->setObjectPHIDs(array_keys($tasks))
|
->setObjectPHIDs(array_keys($tasks))
|
||||||
|
->setFetchAllBoards(true)
|
||||||
->executeLayout();
|
->executeLayout();
|
||||||
|
|
||||||
$columns = $layout_engine->getColumns($board_phid);
|
$columns = $layout_engine->getColumns($board_phid);
|
||||||
if (!$columns) {
|
if (!$columns || !$project->getHasWorkboard()) {
|
||||||
$can_edit = PhabricatorPolicyFilter::hasCapability(
|
$can_edit = PhabricatorPolicyFilter::hasCapability(
|
||||||
$viewer,
|
$viewer,
|
||||||
$project,
|
$project,
|
||||||
PhabricatorPolicyCapability::CAN_EDIT);
|
PhabricatorPolicyCapability::CAN_EDIT);
|
||||||
|
if (!$columns) {
|
||||||
if (!$can_edit) {
|
if (!$can_edit) {
|
||||||
$content = $this->buildNoAccessContent($project);
|
$content = $this->buildNoAccessContent($project);
|
||||||
} else {
|
} else {
|
||||||
$content = $this->buildInitializeContent($project);
|
$content = $this->buildInitializeContent($project);
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
if (!$can_edit) {
|
||||||
|
$content = $this->buildDisabledContent($project);
|
||||||
|
} else {
|
||||||
|
$content = $this->buildEnableContent($project);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if ($content instanceof AphrontResponse) {
|
if ($content instanceof AphrontResponse) {
|
||||||
return $content;
|
return $content;
|
||||||
|
@ -544,6 +553,12 @@ final class PhabricatorProjectBoardViewController
|
||||||
$request = $this->getRequest();
|
$request = $this->getRequest();
|
||||||
$viewer = $request->getUser();
|
$viewer = $request->getUser();
|
||||||
|
|
||||||
|
$id = $project->getID();
|
||||||
|
|
||||||
|
$disable_uri = $this->getApplicationURI("board/{$id}/disable/");
|
||||||
|
$add_uri = $this->getApplicationURI("board/{$id}/edit/");
|
||||||
|
$reorder_uri = $this->getApplicationURI("board/{$id}/reorder/");
|
||||||
|
|
||||||
$can_edit = PhabricatorPolicyFilter::hasCapability(
|
$can_edit = PhabricatorPolicyFilter::hasCapability(
|
||||||
$viewer,
|
$viewer,
|
||||||
$project,
|
$project,
|
||||||
|
@ -554,14 +569,14 @@ final class PhabricatorProjectBoardViewController
|
||||||
$manage_items[] = id(new PhabricatorActionView())
|
$manage_items[] = id(new PhabricatorActionView())
|
||||||
->setIcon('fa-plus')
|
->setIcon('fa-plus')
|
||||||
->setName(pht('Add Column'))
|
->setName(pht('Add Column'))
|
||||||
->setHref($this->getApplicationURI('board/'.$this->id.'/edit/'))
|
->setHref($add_uri)
|
||||||
->setDisabled(!$can_edit)
|
->setDisabled(!$can_edit)
|
||||||
->setWorkflow(!$can_edit);
|
->setWorkflow(!$can_edit);
|
||||||
|
|
||||||
$manage_items[] = id(new PhabricatorActionView())
|
$manage_items[] = id(new PhabricatorActionView())
|
||||||
->setIcon('fa-exchange')
|
->setIcon('fa-exchange')
|
||||||
->setName(pht('Reorder Columns'))
|
->setName(pht('Reorder Columns'))
|
||||||
->setHref($this->getApplicationURI('board/'.$this->id.'/reorder/'))
|
->setHref($reorder_uri)
|
||||||
->setDisabled(!$can_edit)
|
->setDisabled(!$can_edit)
|
||||||
->setWorkflow(true);
|
->setWorkflow(true);
|
||||||
|
|
||||||
|
@ -595,6 +610,13 @@ final class PhabricatorProjectBoardViewController
|
||||||
->setHref($batch_edit_uri)
|
->setHref($batch_edit_uri)
|
||||||
->setDisabled(!$can_batch_edit);
|
->setDisabled(!$can_batch_edit);
|
||||||
|
|
||||||
|
$manage_items[] = id(new PhabricatorActionView())
|
||||||
|
->setIcon('fa-ban')
|
||||||
|
->setName(pht('Disable Workboard'))
|
||||||
|
->setHref($disable_uri)
|
||||||
|
->setWorkflow(true)
|
||||||
|
->setDisabled(!$can_edit);
|
||||||
|
|
||||||
$manage_menu = id(new PhabricatorActionListView())
|
$manage_menu = id(new PhabricatorActionListView())
|
||||||
->setUser($viewer);
|
->setUser($viewer);
|
||||||
foreach ($manage_items as $item) {
|
foreach ($manage_items as $item) {
|
||||||
|
@ -852,4 +874,59 @@ final class PhabricatorProjectBoardViewController
|
||||||
->addCancelButton($profile_uri);
|
->addCancelButton($profile_uri);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private function buildEnableContent(PhabricatorProject $project) {
|
||||||
|
$request = $this->getRequest();
|
||||||
|
$viewer = $this->getViewer();
|
||||||
|
|
||||||
|
$id = $project->getID();
|
||||||
|
$profile_uri = $this->getApplicationURI("profile/{$id}/");
|
||||||
|
$board_uri = $this->getApplicationURI("board/{$id}/");
|
||||||
|
|
||||||
|
if ($request->isFormPost()) {
|
||||||
|
$xactions = array();
|
||||||
|
|
||||||
|
$xactions[] = id(new PhabricatorProjectTransaction())
|
||||||
|
->setTransactionType(PhabricatorProjectTransaction::TYPE_HASWORKBOARD)
|
||||||
|
->setNewValue(1);
|
||||||
|
|
||||||
|
id(new PhabricatorProjectTransactionEditor())
|
||||||
|
->setActor($viewer)
|
||||||
|
->setContentSourceFromRequest($request)
|
||||||
|
->setContinueOnNoEffect(true)
|
||||||
|
->setContinueOnMissingFields(true)
|
||||||
|
->applyTransactions($project, $xactions);
|
||||||
|
|
||||||
|
return id(new AphrontRedirectResponse())
|
||||||
|
->setURI($board_uri);
|
||||||
|
}
|
||||||
|
|
||||||
|
return $this->newDialog()
|
||||||
|
->setTitle(pht('Workboard Disabled'))
|
||||||
|
->addHiddenInput('initialize', 1)
|
||||||
|
->appendParagraph(
|
||||||
|
pht(
|
||||||
|
'This workboard has been disabled, but can be restored to its '.
|
||||||
|
'former glory.'))
|
||||||
|
->addCancelButton($profile_uri)
|
||||||
|
->addSubmitButton(pht('Enable Workboard'));
|
||||||
|
}
|
||||||
|
|
||||||
|
private function buildDisabledContent(PhabricatorProject $project) {
|
||||||
|
$viewer = $this->getViewer();
|
||||||
|
|
||||||
|
$id = $project->getID();
|
||||||
|
|
||||||
|
$profile_uri = $this->getApplicationURI("profile/{$id}/");
|
||||||
|
|
||||||
|
return $this->newDialog()
|
||||||
|
->setTitle(pht('Workboard Disabled'))
|
||||||
|
->appendParagraph(
|
||||||
|
pht(
|
||||||
|
'This workboard has been disabled, and you do not have permission '.
|
||||||
|
'to enable it. Only users who can edit this project can restore '.
|
||||||
|
'the workboard.'))
|
||||||
|
->addCancelButton($profile_uri);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -39,6 +39,7 @@ final class PhabricatorProjectTransactionEditor
|
||||||
$types[] = PhabricatorProjectTransaction::TYPE_LOCKED;
|
$types[] = PhabricatorProjectTransaction::TYPE_LOCKED;
|
||||||
$types[] = PhabricatorProjectTransaction::TYPE_PARENT;
|
$types[] = PhabricatorProjectTransaction::TYPE_PARENT;
|
||||||
$types[] = PhabricatorProjectTransaction::TYPE_MILESTONE;
|
$types[] = PhabricatorProjectTransaction::TYPE_MILESTONE;
|
||||||
|
$types[] = PhabricatorProjectTransaction::TYPE_HASWORKBOARD;
|
||||||
|
|
||||||
return $types;
|
return $types;
|
||||||
}
|
}
|
||||||
|
@ -65,6 +66,8 @@ final class PhabricatorProjectTransactionEditor
|
||||||
return $object->getColor();
|
return $object->getColor();
|
||||||
case PhabricatorProjectTransaction::TYPE_LOCKED:
|
case PhabricatorProjectTransaction::TYPE_LOCKED:
|
||||||
return (int)$object->getIsMembershipLocked();
|
return (int)$object->getIsMembershipLocked();
|
||||||
|
case PhabricatorProjectTransaction::TYPE_HASWORKBOARD:
|
||||||
|
return (int)$object->getHasWorkboard();
|
||||||
case PhabricatorProjectTransaction::TYPE_PARENT:
|
case PhabricatorProjectTransaction::TYPE_PARENT:
|
||||||
case PhabricatorProjectTransaction::TYPE_MILESTONE:
|
case PhabricatorProjectTransaction::TYPE_MILESTONE:
|
||||||
return null;
|
return null;
|
||||||
|
@ -87,6 +90,8 @@ final class PhabricatorProjectTransactionEditor
|
||||||
case PhabricatorProjectTransaction::TYPE_PARENT:
|
case PhabricatorProjectTransaction::TYPE_PARENT:
|
||||||
case PhabricatorProjectTransaction::TYPE_MILESTONE:
|
case PhabricatorProjectTransaction::TYPE_MILESTONE:
|
||||||
return $xaction->getNewValue();
|
return $xaction->getNewValue();
|
||||||
|
case PhabricatorProjectTransaction::TYPE_HASWORKBOARD:
|
||||||
|
return (int)$xaction->getNewValue();
|
||||||
case PhabricatorProjectTransaction::TYPE_SLUGS:
|
case PhabricatorProjectTransaction::TYPE_SLUGS:
|
||||||
return $this->normalizeSlugs($xaction->getNewValue());
|
return $this->normalizeSlugs($xaction->getNewValue());
|
||||||
}
|
}
|
||||||
|
@ -131,6 +136,9 @@ final class PhabricatorProjectTransactionEditor
|
||||||
$object->setMilestoneNumber($number);
|
$object->setMilestoneNumber($number);
|
||||||
$object->setParentProjectPHID($xaction->getNewValue());
|
$object->setParentProjectPHID($xaction->getNewValue());
|
||||||
return;
|
return;
|
||||||
|
case PhabricatorProjectTransaction::TYPE_HASWORKBOARD:
|
||||||
|
$object->setHasWorkboard($xaction->getNewValue());
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
return parent::applyCustomInternalTransaction($object, $xaction);
|
return parent::applyCustomInternalTransaction($object, $xaction);
|
||||||
|
@ -172,6 +180,7 @@ final class PhabricatorProjectTransactionEditor
|
||||||
case PhabricatorProjectTransaction::TYPE_LOCKED:
|
case PhabricatorProjectTransaction::TYPE_LOCKED:
|
||||||
case PhabricatorProjectTransaction::TYPE_PARENT:
|
case PhabricatorProjectTransaction::TYPE_PARENT:
|
||||||
case PhabricatorProjectTransaction::TYPE_MILESTONE:
|
case PhabricatorProjectTransaction::TYPE_MILESTONE:
|
||||||
|
case PhabricatorProjectTransaction::TYPE_HASWORKBOARD:
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -9,6 +9,7 @@ final class PhabricatorBoardLayoutEngine extends Phobject {
|
||||||
private $columnMap = array();
|
private $columnMap = array();
|
||||||
private $objectColumnMap = array();
|
private $objectColumnMap = array();
|
||||||
private $boardLayout = array();
|
private $boardLayout = array();
|
||||||
|
private $fetchAllBoards;
|
||||||
|
|
||||||
private $remQueue = array();
|
private $remQueue = array();
|
||||||
private $addQueue = array();
|
private $addQueue = array();
|
||||||
|
@ -40,6 +41,18 @@ final class PhabricatorBoardLayoutEngine extends Phobject {
|
||||||
return $this->objectPHIDs;
|
return $this->objectPHIDs;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Fetch all boards, even if the board is disabled.
|
||||||
|
*/
|
||||||
|
public function setFetchAllBoards($fetch_all) {
|
||||||
|
$this->fetchAllBoards = $fetch_all;
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getFetchAllBoards() {
|
||||||
|
return $this->fetchAllBoards;
|
||||||
|
}
|
||||||
|
|
||||||
public function executeLayout() {
|
public function executeLayout() {
|
||||||
$viewer = $this->getViewer();
|
$viewer = $this->getViewer();
|
||||||
|
|
||||||
|
@ -301,11 +314,13 @@ final class PhabricatorBoardLayoutEngine extends Phobject {
|
||||||
->execute();
|
->execute();
|
||||||
$boards = mpull($boards, null, 'getPHID');
|
$boards = mpull($boards, null, 'getPHID');
|
||||||
|
|
||||||
|
if (!$this->fetchAllBoards) {
|
||||||
foreach ($boards as $key => $board) {
|
foreach ($boards as $key => $board) {
|
||||||
if (!$board->getHasWorkboard()) {
|
if (!$board->getHasWorkboard()) {
|
||||||
unset($boards[$key]);
|
unset($boards[$key]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return $boards;
|
return $boards;
|
||||||
}
|
}
|
||||||
|
|
|
@ -12,6 +12,7 @@ final class PhabricatorProjectTransaction
|
||||||
const TYPE_LOCKED = 'project:locked';
|
const TYPE_LOCKED = 'project:locked';
|
||||||
const TYPE_PARENT = 'project:parent';
|
const TYPE_PARENT = 'project:parent';
|
||||||
const TYPE_MILESTONE = 'project:milestone';
|
const TYPE_MILESTONE = 'project:milestone';
|
||||||
|
const TYPE_HASWORKBOARD = 'project:hasworkboard';
|
||||||
|
|
||||||
// NOTE: This is deprecated, members are just a normal edge now.
|
// NOTE: This is deprecated, members are just a normal edge now.
|
||||||
const TYPE_MEMBERS = 'project:members';
|
const TYPE_MEMBERS = 'project:members';
|
||||||
|
@ -246,6 +247,17 @@ final class PhabricatorProjectTransaction
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case self::TYPE_HASWORKBOARD:
|
||||||
|
if ($new) {
|
||||||
|
return pht(
|
||||||
|
'%s enabled the workboard for this project.',
|
||||||
|
$author_handle);
|
||||||
|
} else {
|
||||||
|
return pht(
|
||||||
|
'%s disabled the workboard for this project.',
|
||||||
|
$author_handle);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return parent::getTitle();
|
return parent::getTitle();
|
||||||
|
@ -366,6 +378,20 @@ final class PhabricatorProjectTransaction
|
||||||
$object_handle,
|
$object_handle,
|
||||||
$this->renderSlugList($rem));
|
$this->renderSlugList($rem));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
case self::TYPE_HASWORKBOARD:
|
||||||
|
if ($new) {
|
||||||
|
return pht(
|
||||||
|
'%s enabled the workboard for %s.',
|
||||||
|
$author_handle,
|
||||||
|
$object_handle);
|
||||||
|
} else {
|
||||||
|
return pht(
|
||||||
|
'%s disabled the workboard for %s.',
|
||||||
|
$author_handle,
|
||||||
|
$object_handle);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return parent::getTitleForFeed();
|
return parent::getTitleForFeed();
|
||||||
|
|
Loading…
Reference in a new issue