1
0
Fork 0
mirror of https://we.phorge.it/source/phorge.git synced 2024-11-22 14:52:41 +01:00

Workboards - let users delete columns

Summary: Fixes T4408. I had to add a "status" to colum. I think we'll need this once we get fancier anyway but for now we have "active" and deleted.

Test Plan: deleted a column. noted reloaded workboard with all those tasks back in the default colun. loaded a task and saw the initial transaction had a "Disabled" icon next to the deleted workboard. also saw the new transaction back to the default column worked.

Reviewers: epriestley

Reviewed By: epriestley

Subscribers: epriestley, Korvin

Maniphest Tasks: T4408

Differential Revision: https://secure.phabricator.com/D8544
This commit is contained in:
Bob Trahan 2014-03-18 10:40:31 -07:00
parent 1e8ed3e5ff
commit 809e5a0389
9 changed files with 153 additions and 1 deletions

View file

@ -0,0 +1,2 @@
ALTER TABLE {$NAMESPACE}_project.project_column
ADD COLUMN status INT UNSIGNED NOT NULL AFTER name;

View file

@ -0,0 +1,2 @@
ALTER TABLE {$NAMESPACE}_project.project_column
ADD KEY `key_status` (`projectPHID`,`status`,`sequence`);

View file

@ -1843,6 +1843,7 @@ phutil_register_library_map(array(
'PhabricatorProject' => 'applications/project/storage/PhabricatorProject.php', 'PhabricatorProject' => 'applications/project/storage/PhabricatorProject.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',
'PhabricatorProjectBoardDeleteController' => 'applications/project/controller/PhabricatorProjectBoardDeleteController.php',
'PhabricatorProjectBoardEditController' => 'applications/project/controller/PhabricatorProjectBoardEditController.php', 'PhabricatorProjectBoardEditController' => 'applications/project/controller/PhabricatorProjectBoardEditController.php',
'PhabricatorProjectColumn' => 'applications/project/storage/PhabricatorProjectColumn.php', 'PhabricatorProjectColumn' => 'applications/project/storage/PhabricatorProjectColumn.php',
'PhabricatorProjectColumnQuery' => 'applications/project/query/PhabricatorProjectColumnQuery.php', 'PhabricatorProjectColumnQuery' => 'applications/project/query/PhabricatorProjectColumnQuery.php',
@ -4609,6 +4610,7 @@ phutil_register_library_map(array(
), ),
'PhabricatorProjectArchiveController' => 'PhabricatorProjectController', 'PhabricatorProjectArchiveController' => 'PhabricatorProjectController',
'PhabricatorProjectBoardController' => 'PhabricatorProjectController', 'PhabricatorProjectBoardController' => 'PhabricatorProjectController',
'PhabricatorProjectBoardDeleteController' => 'PhabricatorProjectController',
'PhabricatorProjectBoardEditController' => 'PhabricatorProjectController', 'PhabricatorProjectBoardEditController' => 'PhabricatorProjectController',
'PhabricatorProjectColumn' => 'PhabricatorProjectColumn' =>
array( array(

View file

@ -53,6 +53,8 @@ final class PhabricatorApplicationProject extends PhabricatorApplication {
'move/(?P<id>[1-9]\d*)/' => 'PhabricatorProjectMoveController', 'move/(?P<id>[1-9]\d*)/' => 'PhabricatorProjectMoveController',
'board/(?P<projectID>[1-9]\d*)/edit/(?:(?P<id>\d+)/)?' 'board/(?P<projectID>[1-9]\d*)/edit/(?:(?P<id>\d+)/)?'
=> 'PhabricatorProjectBoardEditController', => 'PhabricatorProjectBoardEditController',
'board/(?P<projectID>[1-9]\d*)/delete/(?:(?P<id>\d+)/)?'
=> 'PhabricatorProjectBoardDeleteController',
'update/(?P<id>[1-9]\d*)/(?P<action>[^/]+)/' 'update/(?P<id>[1-9]\d*)/(?P<action>[^/]+)/'
=> 'PhabricatorProjectUpdateController', => 'PhabricatorProjectUpdateController',
'history/(?P<id>[1-9]\d*)/' => 'PhabricatorProjectHistoryController', 'history/(?P<id>[1-9]\d*)/' => 'PhabricatorProjectHistoryController',

View file

@ -30,6 +30,7 @@ final class PhabricatorProjectBoardController
$columns = id(new PhabricatorProjectColumnQuery()) $columns = id(new PhabricatorProjectColumnQuery())
->setViewer($viewer) ->setViewer($viewer)
->withProjectPHIDs(array($project->getPHID())) ->withProjectPHIDs(array($project->getPHID()))
->withStatuses(array(PhabricatorProjectColumn::STATUS_ACTIVE))
->execute(); ->execute();
$columns = mpull($columns, null, 'getSequence'); $columns = mpull($columns, null, 'getSequence');
@ -168,6 +169,13 @@ final class PhabricatorProjectBoardController
->setHref($this->getApplicationURI('board/'.$this->id.'/edit/')) ->setHref($this->getApplicationURI('board/'.$this->id.'/edit/'))
->setIcon('create') ->setIcon('create')
->setDisabled(!$can_edit) ->setDisabled(!$can_edit)
->setWorkflow(!$can_edit))
->addAction(
id(new PhabricatorActionView())
->setName(pht('Delete Column'))
->setHref($this->getApplicationURI('board/'.$this->id.'/delete/'))
->setIcon('delete')
->setDisabled(!$can_edit)
->setWorkflow(!$can_edit)); ->setWorkflow(!$can_edit));
$plist = id(new PHUIPropertyListView()); $plist = id(new PHUIPropertyListView());

View file

@ -0,0 +1,116 @@
<?php
final class PhabricatorProjectBoardDeleteController
extends PhabricatorProjectController {
private $id;
private $projectID;
public function willProcessRequest(array $data) {
$this->projectID = $data['projectID'];
$this->id = idx($data, 'id');
}
public function processRequest() {
$request = $this->getRequest();
$viewer = $request->getUser();
$project = id(new PhabricatorProjectQuery())
->setViewer($viewer)
->requireCapabilities(
array(
PhabricatorPolicyCapability::CAN_VIEW,
PhabricatorPolicyCapability::CAN_EDIT,
))
->withIDs(array($this->projectID))
->executeOne();
if (!$project) {
return new Aphront404Response();
}
$columns = id(new PhabricatorProjectColumnQuery())
->setViewer($viewer)
->withProjectPHIDs(array($project->getPHID()))
->withStatuses(array(PhabricatorProjectColumn::STATUS_ACTIVE))
->requireCapabilities(
array(
PhabricatorPolicyCapability::CAN_VIEW,
PhabricatorPolicyCapability::CAN_EDIT))
->execute();
if (!$columns) {
return new Aphront404Response();
}
$columns = mpull($columns, null, 'getSequence');
$columns = mfilter($columns, 'isDefaultColumn', true);
ksort($columns);
$options = mpull($columns, 'getName', 'getPHID');
$view_uri = $this->getApplicationURI('/board/'.$this->projectID.'/');
$error_view = null;
if ($request->isFormPost()) {
$columns = mpull($columns, null, 'getPHID');
$column_phid = $request->getStr('columnPHID');
$column = $columns[$column_phid];
$has_task_phids = PhabricatorEdgeQuery::loadDestinationPHIDs(
$column_phid,
PhabricatorEdgeConfig::TYPE_COLUMN_HAS_OBJECT);
if ($has_task_phids) {
$error_view = id(new AphrontErrorView())
->setTitle(pht('Column has Tasks!'))
->setErrors(array(pht('A column can not be deleted if it has tasks '.
'in it. Please remove the tasks and try '.
'again.')));
} else {
$column->setStatus(PhabricatorProjectColumn::STATUS_DELETED);
$column->save();
return id(new AphrontRedirectResponse())->setURI($view_uri);
}
}
$form = id(new AphrontFormView())
->setUser($viewer)
->appendChild($error_view)
->appendChild(id(new AphrontFormSelectControl())
->setName('columnPHID')
->setValue(head_key($options))
->setOptions($options)
->setLabel(pht('Column')));
$title = pht('Delete Column');
$submit = $title;
$form->appendChild(
id(new AphrontFormSubmitControl())
->setValue($submit)
->addCancelButton($view_uri));
$crumbs = $this->buildApplicationCrumbs();
$crumbs->addTextCrumb(
$project->getName(),
$this->getApplicationURI('view/'.$project->getID().'/'));
$crumbs->addTextCrumb(
pht('Board'),
$this->getApplicationURI('board/'.$project->getID().'/'));
$crumbs->addTextCrumb($title);
$form_box = id(new PHUIObjectBoxView())
->setHeaderText($title)
->setForm($form);
return $this->buildApplicationPage(
array(
$crumbs,
$form_box,
),
array(
'title' => $title,
'device' => true,
));
}
}

View file

@ -34,6 +34,8 @@ final class PhabricatorProjectPHIDTypeColumn extends PhabricatorPHIDType {
$handle->setName($column->getDisplayName()); $handle->setName($column->getDisplayName());
$handle->setURI('/project/board/'.$column->getProject()->getID().'/'); $handle->setURI('/project/board/'.$column->getProject()->getID().'/');
$handle->setDisabled(
$column->getStatus() == PhabricatorProjectColumn::STATUS_DELETED);
} }
} }

View file

@ -6,6 +6,7 @@ final class PhabricatorProjectColumnQuery
private $ids; private $ids;
private $phids; private $phids;
private $projectPHIDs; private $projectPHIDs;
private $statuses;
public function withIDs(array $ids) { public function withIDs(array $ids) {
$this->ids = $ids; $this->ids = $ids;
@ -22,6 +23,11 @@ final class PhabricatorProjectColumnQuery
return $this; return $this;
} }
public function withStatuses(array $status) {
$this->statuses = $status;
return $this;
}
protected function loadPage() { protected function loadPage() {
$table = new PhabricatorProjectColumn(); $table = new PhabricatorProjectColumn();
$conn_r = $table->establishConnection('r'); $conn_r = $table->establishConnection('r');
@ -87,6 +93,13 @@ final class PhabricatorProjectColumnQuery
$this->projectPHIDs); $this->projectPHIDs);
} }
if ($this->statuses !== null) {
$where[] = qsprintf(
$conn_r,
'status IN (%Ld)',
$this->statuses);
}
$where[] = $this->buildPagingClause($conn_r); $where[] = $this->buildPagingClause($conn_r);
return $this->formatWhereClause($where); return $this->formatWhereClause($where);

View file

@ -4,7 +4,11 @@ final class PhabricatorProjectColumn
extends PhabricatorProjectDAO extends PhabricatorProjectDAO
implements PhabricatorPolicyInterface { implements PhabricatorPolicyInterface {
const STATUS_ACTIVE = 0;
const STATUS_DELETED = 1;
protected $name; protected $name;
protected $status;
protected $projectPHID; protected $projectPHID;
protected $sequence; protected $sequence;
@ -12,7 +16,8 @@ final class PhabricatorProjectColumn
public static function initializeNewColumn(PhabricatorUser $user) { public static function initializeNewColumn(PhabricatorUser $user) {
return id(new PhabricatorProjectColumn()) return id(new PhabricatorProjectColumn())
->setName(''); ->setName('')
->setStatus(self::STATUS_ACTIVE);
} }
public function getConfiguration() { public function getConfiguration() {