Summary:
Ref T10010. These aren't perfect but I think (?) they aren't horribly broken.
- When a project is a parent project, destroy (as far as the user can tell) any custom columns.
- When a project has milestones, automatically generate columns on the project's workboard (if it has a workboard).
- When you move tasks between milestones, add the proper milestone tag.
- When you move tasks out of milestones back into the backlog, add the proper parent project tag.
- (Plenty of UI / design stuff to adjust.)
Test Plan:
- Dragged stuff between milestone columns.
- Used a normal workboard.
- Wasn't able to find any egregiously bad cases that did anything terrible.
{F1088224}
Reviewers: chad
Reviewed By: chad
Maniphest Tasks: T10010
Differential Revision: https://secure.phabricator.com/D15171
220 lines
5.0 KiB
PHP
220 lines
5.0 KiB
PHP
<?php
|
|
|
|
final class PhabricatorProjectColumn
|
|
extends PhabricatorProjectDAO
|
|
implements
|
|
PhabricatorApplicationTransactionInterface,
|
|
PhabricatorPolicyInterface,
|
|
PhabricatorDestructibleInterface {
|
|
|
|
const STATUS_ACTIVE = 0;
|
|
const STATUS_HIDDEN = 1;
|
|
|
|
const DEFAULT_ORDER = 'natural';
|
|
const ORDER_NATURAL = 'natural';
|
|
const ORDER_PRIORITY = 'priority';
|
|
|
|
protected $name;
|
|
protected $status;
|
|
protected $projectPHID;
|
|
protected $proxyPHID;
|
|
protected $sequence;
|
|
protected $properties = array();
|
|
|
|
private $project = self::ATTACHABLE;
|
|
private $proxy = self::ATTACHABLE;
|
|
|
|
public static function initializeNewColumn(PhabricatorUser $user) {
|
|
return id(new PhabricatorProjectColumn())
|
|
->setName('')
|
|
->setStatus(self::STATUS_ACTIVE);
|
|
}
|
|
|
|
protected function getConfiguration() {
|
|
return array(
|
|
self::CONFIG_AUX_PHID => true,
|
|
self::CONFIG_SERIALIZATION => array(
|
|
'properties' => self::SERIALIZATION_JSON,
|
|
),
|
|
self::CONFIG_COLUMN_SCHEMA => array(
|
|
'name' => 'text255',
|
|
'status' => 'uint32',
|
|
'sequence' => 'uint32',
|
|
'proxyPHID' => 'phid?',
|
|
),
|
|
self::CONFIG_KEY_SCHEMA => array(
|
|
'key_status' => array(
|
|
'columns' => array('projectPHID', 'status', 'sequence'),
|
|
),
|
|
'key_sequence' => array(
|
|
'columns' => array('projectPHID', 'sequence'),
|
|
),
|
|
'key_proxy' => array(
|
|
'columns' => array('projectPHID', 'proxyPHID'),
|
|
'unique' => true,
|
|
),
|
|
),
|
|
) + parent::getConfiguration();
|
|
}
|
|
|
|
public function generatePHID() {
|
|
return PhabricatorPHID::generateNewPHID(
|
|
PhabricatorProjectColumnPHIDType::TYPECONST);
|
|
}
|
|
|
|
public function attachProject(PhabricatorProject $project) {
|
|
$this->project = $project;
|
|
return $this;
|
|
}
|
|
|
|
public function getProject() {
|
|
return $this->assertAttached($this->project);
|
|
}
|
|
|
|
public function attachProxy($proxy) {
|
|
$this->proxy = $proxy;
|
|
return $this;
|
|
}
|
|
|
|
public function getProxy() {
|
|
return $this->assertAttached($this->proxy);
|
|
}
|
|
|
|
public function isDefaultColumn() {
|
|
return (bool)$this->getProperty('isDefault');
|
|
}
|
|
|
|
public function isHidden() {
|
|
return ($this->getStatus() == self::STATUS_HIDDEN);
|
|
}
|
|
|
|
public function getDisplayName() {
|
|
$proxy = $this->getProxy();
|
|
if ($proxy) {
|
|
return $proxy->getProxyColumnName();
|
|
}
|
|
|
|
$name = $this->getName();
|
|
if (strlen($name)) {
|
|
return $name;
|
|
}
|
|
|
|
if ($this->isDefaultColumn()) {
|
|
return pht('Backlog');
|
|
}
|
|
|
|
return pht('Unnamed Column');
|
|
}
|
|
|
|
public function getDisplayType() {
|
|
if ($this->isDefaultColumn()) {
|
|
return pht('(Default)');
|
|
}
|
|
if ($this->isHidden()) {
|
|
return pht('(Hidden)');
|
|
}
|
|
|
|
return null;
|
|
}
|
|
|
|
public function getDisplayClass() {
|
|
$proxy = $this->getProxy();
|
|
if ($proxy) {
|
|
return $proxy->getProxyColumnClass();
|
|
}
|
|
|
|
return null;
|
|
}
|
|
|
|
public function getHeaderIcon() {
|
|
$proxy = $this->getProxy();
|
|
if ($proxy) {
|
|
return $proxy->getProxyColumnIcon();
|
|
}
|
|
|
|
if ($this->isHidden()) {
|
|
return 'fa-eye-slash';
|
|
}
|
|
|
|
return null;
|
|
}
|
|
|
|
public function getProperty($key, $default = null) {
|
|
return idx($this->properties, $key, $default);
|
|
}
|
|
|
|
public function setProperty($key, $value) {
|
|
$this->properties[$key] = $value;
|
|
return $this;
|
|
}
|
|
|
|
public function getPointLimit() {
|
|
return $this->getProperty('pointLimit');
|
|
}
|
|
|
|
public function setPointLimit($limit) {
|
|
$this->setProperty('pointLimit', $limit);
|
|
return $this;
|
|
}
|
|
|
|
|
|
/* -( PhabricatorApplicationTransactionInterface )------------------------- */
|
|
|
|
|
|
public function getApplicationTransactionEditor() {
|
|
return new PhabricatorProjectColumnTransactionEditor();
|
|
}
|
|
|
|
public function getApplicationTransactionObject() {
|
|
return $this;
|
|
}
|
|
|
|
public function getApplicationTransactionTemplate() {
|
|
return new PhabricatorProjectColumnTransaction();
|
|
}
|
|
|
|
public function willRenderTimeline(
|
|
PhabricatorApplicationTransactionView $timeline,
|
|
AphrontRequest $request) {
|
|
|
|
return $timeline;
|
|
}
|
|
|
|
|
|
/* -( PhabricatorPolicyInterface )----------------------------------------- */
|
|
|
|
|
|
public function getCapabilities() {
|
|
return array(
|
|
PhabricatorPolicyCapability::CAN_VIEW,
|
|
PhabricatorPolicyCapability::CAN_EDIT,
|
|
);
|
|
}
|
|
|
|
public function getPolicy($capability) {
|
|
return $this->getProject()->getPolicy($capability);
|
|
}
|
|
|
|
public function hasAutomaticCapability($capability, PhabricatorUser $viewer) {
|
|
return $this->getProject()->hasAutomaticCapability(
|
|
$capability,
|
|
$viewer);
|
|
}
|
|
|
|
public function describeAutomaticCapability($capability) {
|
|
return pht('Users must be able to see a project to see its board.');
|
|
}
|
|
|
|
|
|
/* -( PhabricatorDestructibleInterface )----------------------------------- */
|
|
|
|
public function destroyObjectPermanently(
|
|
PhabricatorDestructionEngine $engine) {
|
|
|
|
$this->openTransaction();
|
|
$this->delete();
|
|
$this->saveTransaction();
|
|
}
|
|
|
|
}
|