diff --git a/src/applications/project/controller/PhabricatorProjectBoardReorderController.php b/src/applications/project/controller/PhabricatorProjectBoardReorderController.php --- a/src/applications/project/controller/PhabricatorProjectBoardReorderController.php +++ b/src/applications/project/controller/PhabricatorProjectBoardReorderController.php @@ -97,9 +97,20 @@ ->setFlush(true); foreach ($columns as $column) { + // Don't allow milestone columns to be reordered. + $proxy = $column->getProxy(); + if ($proxy && $proxy->isMilestone()) { + continue; + } + + // At least for now, don't show subproject column. + if ($proxy) { + continue; + } + $item = id(new PHUIObjectItemView()) ->setHeader($column->getDisplayName()) - ->addIcon('none', $column->getDisplayType()); + ->addIcon($column->getHeaderIcon(), $column->getDisplayType()); if ($column->isHidden()) { $item->setDisabled(true); diff --git a/src/applications/project/controller/PhabricatorProjectColumnDetailController.php b/src/applications/project/controller/PhabricatorProjectColumnDetailController.php --- a/src/applications/project/controller/PhabricatorProjectColumnDetailController.php +++ b/src/applications/project/controller/PhabricatorProjectColumnDetailController.php @@ -22,6 +22,8 @@ } $this->setProject($project); + $project_id = $project->getID(); + $column = id(new PhabricatorProjectColumnQuery()) ->setViewer($viewer) ->withIDs(array($id)) @@ -45,6 +47,10 @@ $actions = $this->buildActionView($column); $properties = $this->buildPropertyView($column, $actions); + $crumbs = $this->buildApplicationCrumbs(); + $crumbs->addTextCrumb(pht('Workboard'), "/project/board/{$project_id}/"); + $crumbs->addTextCrumb(pht('Column: %s', $title)); + $box = id(new PHUIObjectBoxView()) ->setHeader($header) ->addPropertyList($properties); @@ -54,6 +60,7 @@ return $this->newPage() ->setTitle($title) ->setNavigation($nav) + ->setCrumbs($crumbs) ->appendChild( array( $box, diff --git a/src/applications/project/controller/PhabricatorProjectColumnEditController.php b/src/applications/project/controller/PhabricatorProjectColumnEditController.php --- a/src/applications/project/controller/PhabricatorProjectColumnEditController.php +++ b/src/applications/project/controller/PhabricatorProjectColumnEditController.php @@ -81,10 +81,12 @@ $xactions = array(); - $type_name = PhabricatorProjectColumnTransaction::TYPE_NAME; - $xactions[] = id(new PhabricatorProjectColumnTransaction()) - ->setTransactionType($type_name) - ->setNewValue($v_name); + if (!$column->getProxy()) { + $type_name = PhabricatorProjectColumnTransaction::TYPE_NAME; + $xactions[] = id(new PhabricatorProjectColumnTransaction()) + ->setTransactionType($type_name) + ->setNewValue($v_name); + } $type_limit = PhabricatorProjectColumnTransaction::TYPE_LIMIT; $xactions[] = id(new PhabricatorProjectColumnTransaction()) @@ -105,26 +107,26 @@ } } - $form = new AphrontFormView(); - $form - ->setUser($request->getUser()) - ->appendChild( + $form = id(new AphrontFormView()) + ->setUser($request->getUser()); + + if (!$column->getProxy()) { + $form->appendChild( id(new AphrontFormTextControl()) ->setValue($v_name) ->setLabel(pht('Name')) ->setName('name') - ->setError($e_name) - ->setCaption( - pht('This will be displayed as the header of the column.'))) - ->appendChild( - id(new AphrontFormTextControl()) - ->setValue($v_limit) - ->setLabel(pht('Point Limit')) - ->setName('limit') - ->setError($e_limit) - ->setCaption( - pht('Maximum number of points of tasks allowed in the column.'))); + ->setError($e_name)); + } + $form->appendChild( + id(new AphrontFormTextControl()) + ->setValue($v_limit) + ->setLabel(pht('Point Limit')) + ->setName('limit') + ->setError($e_limit) + ->setCaption( + pht('Maximum number of points of tasks allowed in the column.'))); if ($is_new) { $title = pht('Create Column'); diff --git a/src/applications/project/engine/PhabricatorBoardLayoutEngine.php b/src/applications/project/engine/PhabricatorBoardLayoutEngine.php --- a/src/applications/project/engine/PhabricatorBoardLayoutEngine.php +++ b/src/applications/project/engine/PhabricatorBoardLayoutEngine.php @@ -317,7 +317,7 @@ ->setViewer($viewer) ->withProjectPHIDs(array_keys($boards)) ->execute(); - $columns = msort($columns, 'getSequence'); + $columns = msort($columns, 'getOrderingKey'); $columns = mpull($columns, null, 'getPHID'); $need_children = array(); @@ -368,6 +368,8 @@ } } + $board_columns = msort($board_columns, 'getOrderingKey'); + $columns[$board_phid] = $board_columns; } diff --git a/src/applications/project/storage/PhabricatorProjectColumn.php b/src/applications/project/storage/PhabricatorProjectColumn.php --- a/src/applications/project/storage/PhabricatorProjectColumn.php +++ b/src/applications/project/storage/PhabricatorProjectColumn.php @@ -27,7 +27,8 @@ public static function initializeNewColumn(PhabricatorUser $user) { return id(new PhabricatorProjectColumn()) ->setName('') - ->setStatus(self::STATUS_ACTIVE); + ->setStatus(self::STATUS_ACTIVE) + ->attachProxy(null); } protected function getConfiguration() { @@ -157,6 +158,25 @@ return $this; } + public function getOrderingKey() { + $proxy = $this->getProxy(); + + // Normal columns and subproject columns go first, in a user-controlled + // order. + + // All the milestone columns go last, in their sequential order. + + if (!$proxy || !$proxy->isMilestone()) { + $group = 'A'; + $sequence = $this->getSequence(); + } else { + $group = 'B'; + $sequence = $proxy->getMilestoneNumber(); + } + + return sprintf('%s%012d', $group, $sequence); + } + /* -( PhabricatorApplicationTransactionInterface )------------------------- */