@recaptime-dev's working patches + fork for Phorge, a community fork of Phabricator. (Upstream dev and stable branches are at upstream/main and upstream/stable respectively.) hq.recaptime.dev/wiki/Phorge
phorge phabricator
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

"Hide" columns instead of "Deleting" them

Summary:
Fixes T5342. Fixes T5161. Previously, we were a bit strict about deleting columns because you could orphan tasks. Let users recover these columns more easily so they can't shoot themselves in the foot.

- Change "Delete" language to "Hide".
- Add a button to let you see hidden columns.
- Remove restriction that you can only delete empty columns.

The new button is a little funky, but maybe it merges into the "Add Column" button and that becomes a dropdown with board actions? The rest of this feels OK to me.

Test Plan: See screenshot.

Reviewers: chad

Reviewed By: chad

Subscribers: epriestley

Maniphest Tasks: T5342, T5161

Differential Revision: https://secure.phabricator.com/D9719

+70 -60
+17 -37
src/applications/project/controller/PhabricatorProjectBoardDeleteController.php
··· 41 41 return new Aphront404Response(); 42 42 } 43 43 44 - $error_view = null; 45 44 $column_phid = $column->getPHID(); 46 - $has_task_phids = PhabricatorEdgeQuery::loadDestinationPHIDs( 47 - $column_phid, 48 - PhabricatorEdgeConfig::TYPE_COLUMN_HAS_OBJECT); 49 - 50 - if ($has_task_phids) { 51 - $error_view = id(new AphrontErrorView()) 52 - ->setTitle(pht('Column has Tasks!')); 53 - if ($column->isDeleted()) { 54 - $error_view->setErrors(array(pht( 55 - 'A column can not be activated if it has tasks '. 56 - 'in it. Please remove the tasks and try again.'))); 57 - } else { 58 - $error_view->setErrors(array(pht( 59 - 'A column can not be deleted if it has tasks '. 60 - 'in it. Please remove the tasks and try again.'))); 61 - } 62 - } 63 45 64 46 $view_uri = $this->getApplicationURI( 65 47 '/board/'.$this->projectID.'/column/'.$this->id.'/'); 66 48 67 - if ($request->isFormPost() && !$error_view) { 68 - if ($column->isDeleted()) { 49 + if ($request->isFormPost()) { 50 + if ($column->isHidden()) { 69 51 $new_status = PhabricatorProjectColumn::STATUS_ACTIVE; 70 52 } else { 71 - $new_status = PhabricatorProjectColumn::STATUS_DELETED; 53 + $new_status = PhabricatorProjectColumn::STATUS_HIDDEN; 72 54 } 73 55 74 56 $type_status = PhabricatorProjectColumnTransaction::TYPE_STATUS; ··· 85 67 return id(new AphrontRedirectResponse())->setURI($view_uri); 86 68 } 87 69 88 - if ($column->isDeleted()) { 89 - $title = pht('Activate Column'); 70 + if ($column->isHidden()) { 71 + $title = pht('Show Column'); 90 72 } else { 91 - $title = pht('Delete Column'); 73 + $title = pht('Hide Column'); 92 74 } 93 - $submit = $title; 94 - if ($error_view) { 95 - $body = $error_view; 96 - } else if ($column->isDeleted()) { 97 - $body = pht('Are you sure you want to activate this column?'); 75 + 76 + if ($column->isHidden()) { 77 + $body = pht( 78 + 'Are you sure you want to show this column?'); 98 79 } else { 99 - $body = pht('Are you sure you want to delete this column?'); 80 + $body = pht( 81 + 'Are you sure you want to hide this column? It will no longer '. 82 + 'appear on the workboard.'); 100 83 } 101 84 102 - $dialog = id(new AphrontDialogView()) 103 - ->setUser($viewer) 85 + $dialog = $this->newDialog() 104 86 ->setWidth(AphrontDialogView::WIDTH_FORM) 105 87 ->setTitle($title) 106 88 ->appendChild($body) 107 89 ->setDisableWorkflowOnCancel(true) 108 - ->addSubmitButton($title) 109 - ->addCancelButton($view_uri); 90 + ->addCancelButton($view_uri) 91 + ->addSubmitButton($title); 110 92 111 - return id(new AphrontDialogResponse()) 112 - ->setDialog($dialog); 113 - 93 + return $dialog; 114 94 } 115 95 }
+34 -7
src/applications/project/controller/PhabricatorProjectBoardViewController.php
··· 24 24 $request = $this->getRequest(); 25 25 $viewer = $request->getUser(); 26 26 27 + $show_hidden = $request->getBool('hidden'); 28 + 27 29 $project = id(new PhabricatorProjectQuery()) 28 30 ->setViewer($viewer) 29 31 ->needImages(true); ··· 39 41 40 42 $this->setProject($project); 41 43 42 - $columns = id(new PhabricatorProjectColumnQuery()) 44 + $column_query = id(new PhabricatorProjectColumnQuery()) 43 45 ->setViewer($viewer) 44 - ->withProjectPHIDs(array($project->getPHID())) 45 - ->withStatuses(array(PhabricatorProjectColumn::STATUS_ACTIVE)) 46 - ->execute(); 46 + ->withProjectPHIDs(array($project->getPHID())); 47 + 48 + if (!$show_hidden) { 49 + $column_query->withStatuses( 50 + array(PhabricatorProjectColumn::STATUS_ACTIVE)); 51 + } 47 52 53 + $columns = $column_query->execute(); 48 54 $columns = mpull($columns, null, 'getSequence'); 49 55 50 56 // If there's no default column, create one now. ··· 168 174 $panel = id(new PHUIWorkpanelView()) 169 175 ->setHeader($column->getDisplayName()) 170 176 ->setHeaderColor($column->getHeaderColor()); 177 + 171 178 if (!$column->isDefaultColumn()) { 172 179 $panel->setEditURI($board_uri.'column/'.$column->getID().'/'); 173 180 } 181 + 174 182 $panel->setHeaderAction(id(new PHUIIconView()) 175 183 ->setIconFont('fa-plus') 176 184 ->setHref('/maniphest/task/create/') ··· 187 195 array( 188 196 'columnPHID' => $column->getPHID(), 189 197 )); 198 + 190 199 $task_phids = idx($task_map, $column->getPHID(), array()); 191 200 foreach (array_select_keys($tasks, $task_phids) as $task) { 192 201 $owner = null; ··· 282 291 ->setWorkflow(true) 283 292 ->setName(pht('Advanced Filter...')); 284 293 285 - 286 - 287 294 $filter_menu = id(new PhabricatorActionListView()) 288 295 ->setUser($viewer); 289 296 foreach ($items as $item) { ··· 296 303 ->setTag('a') 297 304 ->setHref('#') 298 305 ->addSigil('boards-filter-menu') 299 - 300 306 ->setMetadata( 301 307 array( 302 308 'items' => hsprintf('%s', $filter_menu), ··· 309 315 ), 310 316 $project->getName()); 311 317 318 + if ($show_hidden) { 319 + $hidden_uri = $request->getRequestURI() 320 + ->setQueryParam('hidden', null); 321 + $hidden_icon = id(new PHUIIconView()) 322 + ->setIconFont('fa-eye-slash bluegrey'); 323 + $hidden_text = pht('Hide Hidden Columns'); 324 + } else { 325 + $hidden_uri = $request->getRequestURI() 326 + ->setQueryParam('hidden', 'true'); 327 + $hidden_icon = id(new PHUIIconView()) 328 + ->setIconFont('fa-eye bluegrey'); 329 + $hidden_text = pht('Show Hidden Columns'); 330 + } 331 + 332 + $hidden_button = id(new PHUIButtonView()) 333 + ->setText($hidden_text) 334 + ->setIcon($hidden_icon) 335 + ->setTag('a') 336 + ->setHref($hidden_uri); 337 + 312 338 $header = id(new PHUIHeaderView()) 313 339 ->setHeader($header_link) 314 340 ->setUser($viewer) 315 341 ->setNoBackground(true) 316 342 ->setImage($project->getProfileImageURI()) 317 343 ->setImageURL($this->getApplicationURI('view/'.$project->getID().'/')) 344 + ->addActionLink($hidden_button) 318 345 ->addActionLink($filter_button) 319 346 ->addActionLink($add_button) 320 347 ->setPolicyObject($project);
+8 -8
src/applications/project/controller/PhabricatorProjectColumnDetailController.php
··· 88 88 ->setHeader($column->getName()) 89 89 ->setPolicyObject($column); 90 90 91 - if ($column->isDeleted()) { 92 - $header->setStatus('fa-ban', 'dark', pht('Deleted')); 91 + if ($column->isHidden()) { 92 + $header->setStatus('fa-ban', 'dark', pht('Hidden')); 93 93 } 94 94 95 95 return $header; ··· 113 113 114 114 $actions->addAction( 115 115 id(new PhabricatorActionView()) 116 - ->setName(pht('Edit column')) 116 + ->setName(pht('Edit Column')) 117 117 ->setIcon('fa-pencil') 118 118 ->setHref($this->getApplicationURI($base_uri.'edit/'.$id.'/')) 119 119 ->setDisabled(!$can_edit) 120 120 ->setWorkflow(!$can_edit)); 121 121 122 - if (!$column->isDeleted()) { 122 + if (!$column->isHidden()) { 123 123 $actions->addAction( 124 124 id(new PhabricatorActionView()) 125 - ->setName(pht('Delete column')) 126 - ->setIcon('fa-times') 125 + ->setName(pht('Hide Column')) 126 + ->setIcon('fa-eye-slash') 127 127 ->setHref($this->getApplicationURI($base_uri.'delete/'.$id.'/')) 128 128 ->setDisabled(!$can_edit) 129 129 ->setWorkflow(true)); 130 130 } else { 131 131 $actions->addAction( 132 132 id(new PhabricatorActionView()) 133 - ->setName(pht('Activate column')) 134 - ->setIcon('fa-play-circle-o') 133 + ->setName(pht('Show Column')) 134 + ->setIcon('fa-eye') 135 135 ->setHref($this->getApplicationURI($base_uri.'delete/'.$id.'/')) 136 136 ->setDisabled(!$can_edit) 137 137 ->setWorkflow(true));
+1 -2
src/applications/project/phid/PhabricatorProjectPHIDTypeColumn.php
··· 38 38 39 39 $handle->setName($column->getDisplayName()); 40 40 $handle->setURI('/project/board/'.$column->getProject()->getID().'/'); 41 - $handle->setDisabled( 42 - $column->getStatus() == PhabricatorProjectColumn::STATUS_DELETED); 41 + $handle->setDisabled($column->isHidden()); 43 42 } 44 43 } 45 44
+7 -3
src/applications/project/storage/PhabricatorProjectColumn.php
··· 6 6 PhabricatorDestructableInterface { 7 7 8 8 const STATUS_ACTIVE = 0; 9 - const STATUS_DELETED = 1; 9 + const STATUS_HIDDEN = 1; 10 10 11 11 protected $name; 12 12 protected $status; ··· 45 45 return ($this->getSequence() == 0); 46 46 } 47 47 48 - public function isDeleted() { 49 - return ($this->getStatus() == self::STATUS_DELETED); 48 + public function isHidden() { 49 + return ($this->getStatus() == self::STATUS_HIDDEN); 50 50 } 51 51 52 52 public function getDisplayName() { ··· 57 57 } 58 58 59 59 public function getHeaderColor() { 60 + if ($this->isHidden()) { 61 + return PHUIActionHeaderView::HEADER_LIGHTRED; 62 + } 63 + 60 64 if ($this->isDefaultColumn()) { 61 65 return PHUIActionHeaderView::HEADER_DARK_GREY; 62 66 }
+3 -3
src/applications/project/storage/PhabricatorProjectColumnTransaction.php
··· 36 36 switch ($new) { 37 37 case PhabricatorProjectColumn::STATUS_ACTIVE: 38 38 return pht( 39 - '%s activated this column.', 39 + '%s marked this column visible.', 40 40 $author_handle); 41 - case PhabricatorProjectColumn::STATUS_DELETED: 41 + case PhabricatorProjectColumn::STATUS_HIDDEN: 42 42 return pht( 43 - '%s deleted this column.', 43 + '%s marked this column hidden.', 44 44 $author_handle); 45 45 } 46 46 break;