@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.

Workboard: Milestone Name easily editable (instead of surfing 3 pages)

Summary:
After this change, a new input field "Milestone Name" appears in the "Edit" menu of a Milestone:

| Before | After |
|-----------|-----------|
| {F314008} | {F314005} |

So you can quickly change the name of your Milestones, from a Workboard.

Before this change, from a Workboard, this was the way to rename a Milestone:

1. click on the Milestone name (yes, that is a link)
2. click on Manage
3. click on Edit Details
4. rename
5. Save
6. Manually visit again the Project's Workboard

After this change, from a Workboard, you just need to:

1. click on Milestone > Edit
2. click on Edit Column
3. rename
4. Save

Example usage:

{F314015}

This does not change the level of permissions needed: if you have not enough
permissions to see or edit a Milestone, you cannot access this feature indeed.

In short, this is just a frontend change, keeping current policies as-is.

Closes T15143

Test Plan:
Create a Project or use an existing editable one.

Create a Milestone called "Test Milestone". You can create Milestones visiting the Project's menu {nav icon=sitemap,name=Subprojects > icon=plus,name=Create next milestone}

Visit the Project's Workboard. Find the column "Test Milestone". Click the Edit button on a Milestone, and:

- try to save another name: it must work
- try to save an empty name: nice error message shown
- try to save both the score points and the name: it must work
- try to save "FOO" as Points: you still see the error message

Also:

- do the same for the Backlog column: it still works (name still allowed to be empty)
- do the same for a "normal" Column (not the Backlog): it still work (name still __not__ allowed to be empty)

Reviewers: O1 Blessed Committers, Cigaryno, 20after4, waldyrious

Reviewed By: O1 Blessed Committers, Cigaryno, 20after4, waldyrious

Subscribers: waldyrious, brennen, aklapper, 20after4, speck, tobiaswiese, Matthew, Cigaryno

Maniphest Tasks: T15143

Differential Revision: https://we.phorge.it/D25066

+56 -3
+56 -3
src/applications/project/controller/PhabricatorProjectColumnEditController.php
··· 45 45 46 46 $e_name = null; 47 47 $e_limit = null; 48 + $e_milestone_name = null; 48 49 49 50 $v_limit = $column->getPointLimit(); 50 51 $v_name = $column->getName(); 52 + 53 + $proxy = $column->getProxy(); 54 + 55 + // Is this a normal Column? Example: when true, this is not a Milestone. 56 + $is_column = !$proxy; 57 + 58 + // Is this a Milestone? Example: when true, this is not a normal Column. 59 + $is_milestone = $proxy && $proxy->isMilestone(); 60 + 61 + // Milestone name, eventually coming from the proxed object. 62 + $v_milestone_name = null; 63 + if ($is_milestone) { 64 + $v_milestone_name = $proxy->getName(); 65 + } 51 66 52 67 $validation_exception = null; 53 68 $view_uri = $project->getWorkboardURI(); ··· 55 70 if ($request->isFormPost()) { 56 71 $v_name = $request->getStr('name'); 57 72 $v_limit = $request->getStr('limit'); 73 + $v_milestone_name = $request->getStr('milestone.name'); 58 74 59 75 if ($is_new) { 60 76 $column->setProjectPHID($project->getPHID()); ··· 74 90 } 75 91 76 92 $xactions = array(); 93 + $xactions_milestone = array(); 77 94 78 95 $type_name = PhabricatorProjectColumnNameTransaction::TRANSACTIONTYPE; 79 96 $type_limit = PhabricatorProjectColumnLimitTransaction::TRANSACTIONTYPE; 97 + $type_project_name = PhabricatorProjectNameTransaction::TRANSACTIONTYPE; 80 98 81 - if (!$column->getProxy()) { 99 + if ($is_column) { 100 + // Transaction for Column name. 82 101 $xactions[] = id(new PhabricatorProjectColumnTransaction()) 83 102 ->setTransactionType($type_name) 84 103 ->setNewValue($v_name); 104 + } else if ($is_milestone) { 105 + // Transaction for Milestone name (that internally is a Project Name). 106 + $xactions_milestone[] = id(new PhabricatorProjectTransaction()) 107 + ->setTransactionType($type_project_name) 108 + ->setNewValue($v_milestone_name); 85 109 } 86 110 87 111 $xactions[] = id(new PhabricatorProjectColumnTransaction()) ··· 94 118 ->setContinueOnNoEffect(true) 95 119 ->setContentSourceFromRequest($request) 96 120 ->applyTransactions($column, $xactions); 97 - return id(new AphrontRedirectResponse())->setURI($view_uri); 98 121 } catch (PhabricatorApplicationTransactionValidationException $ex) { 122 + // Error messages related to the Column (like invalid Name, etc.) 99 123 $e_name = $ex->getShortMessage($type_name); 100 124 $e_limit = $ex->getShortMessage($type_limit); 101 125 $validation_exception = $ex; 102 126 } 127 + 128 + // Save Milestone-related stuff but only if there were no prior problems 129 + // and only if we have changes. 130 + if (!$validation_exception && $xactions_milestone) { 131 + try { 132 + $editor_milestone = id(new PhabricatorProjectTransactionEditor()) 133 + ->setActor($viewer) 134 + ->setContinueOnNoEffect(true) 135 + ->setContentSourceFromRequest($request) 136 + ->applyTransactions($proxy, $xactions_milestone); 137 + } catch (PhabricatorApplicationTransactionValidationException $ex) { 138 + // Error messages related to the Milestone (like invalid Name, etc.) 139 + $e_milestone_name = $ex->getShortMessage($type_project_name); 140 + $validation_exception = $ex; 141 + } 142 + } 143 + 144 + // Refresh the page only if there are no errors to show. 145 + if (!$validation_exception) { 146 + return id(new AphrontRedirectResponse())->setURI($view_uri); 147 + } 103 148 } 104 149 105 150 $form = id(new AphrontFormView()) 106 151 ->setUser($request->getUser()); 107 152 108 - if (!$column->getProxy()) { 153 + // Show the most appropriate input field for the name. 154 + if ($is_column) { 109 155 $form->appendChild( 110 156 id(new AphrontFormTextControl()) 111 157 ->setValue($v_name) 112 158 ->setLabel(pht('Name')) 113 159 ->setName('name') 114 160 ->setError($e_name)); 161 + } else if ($is_milestone) { 162 + $form->appendChild( 163 + id(new AphrontFormTextControl()) 164 + ->setValue($v_milestone_name) 165 + ->setLabel(pht('Milestone Name')) 166 + ->setName('milestone.name') 167 + ->setError($e_milestone_name)); 115 168 } 116 169 117 170 $form->appendChild(