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

Add a one-click "Scuttle Task" button to Maniphest

Summary: Fixes T4657. See that task for discussion of edge cases.

Test Plan: {F132941}

Reviewers: btrahan

Reviewed By: btrahan

Subscribers: chad, carl, epriestley

Maniphest Tasks: T4657

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

+122 -48
+13 -13
resources/celerity/map.php
··· 7 7 return array( 8 8 'names' => 9 9 array( 10 - 'core.pkg.css' => '5e574aa1', 11 - 'core.pkg.js' => '264721e1', 10 + 'core.pkg.css' => '6d16f22a', 11 + 'core.pkg.js' => 'd3fecc57', 12 12 'darkconsole.pkg.js' => 'ca8671ce', 13 13 'differential.pkg.css' => 'cb97e095', 14 14 'differential.pkg.js' => '11a5b750', ··· 132 132 'rsrc/css/phui/phui-document.css' => '10f59385', 133 133 'rsrc/css/phui/phui-feed-story.css' => '3a59c2cf', 134 134 'rsrc/css/phui/phui-fontkit.css' => 'de84aa4a', 135 - 'rsrc/css/phui/phui-form-view.css' => '0efd3326', 135 + 'rsrc/css/phui/phui-form-view.css' => '867463b4', 136 136 'rsrc/css/phui/phui-form.css' => 'b78ec020', 137 137 'rsrc/css/phui/phui-header-view.css' => '5b79f0ef', 138 138 'rsrc/css/phui/phui-icon.css' => '7a5771a9', ··· 475 475 'rsrc/js/core/behavior-tokenizer.js' => 'b3a4b884', 476 476 'rsrc/js/core/behavior-tooltip.js' => '48db4145', 477 477 'rsrc/js/core/behavior-watch-anchor.js' => '06e05112', 478 - 'rsrc/js/core/behavior-workflow.js' => '82947dda', 478 + 'rsrc/js/core/behavior-workflow.js' => 'fee00761', 479 479 'rsrc/js/core/phtize.js' => 'd254d646', 480 480 'rsrc/js/phui/behavior-phui-object-box-tabs.js' => 'a3e2244e', 481 481 'rsrc/swf/aphlict.swf' => 'abac967d', ··· 627 627 'javelin-behavior-test-payment-form' => 'b3e5ee60', 628 628 'javelin-behavior-toggle-class' => 'a82a7769', 629 629 'javelin-behavior-view-placeholder' => '2fa810fc', 630 - 'javelin-behavior-workflow' => '82947dda', 630 + 'javelin-behavior-workflow' => 'fee00761', 631 631 'javelin-color' => '7e41274a', 632 632 'javelin-cookie' => '6b3dcf44', 633 633 'javelin-dom' => '5054855f', ··· 748 748 'phui-feed-story-css' => '3a59c2cf', 749 749 'phui-fontkit-css' => 'de84aa4a', 750 750 'phui-form-css' => 'b78ec020', 751 - 'phui-form-view-css' => '0efd3326', 751 + 'phui-form-view-css' => '867463b4', 752 752 'phui-header-view-css' => '5b79f0ef', 753 753 'phui-icon-view-css' => '7a5771a9', 754 754 'phui-info-panel-css' => '27ea50a1', ··· 1330 1330 0 => 'javelin-behavior', 1331 1331 1 => 'javelin-history', 1332 1332 ), 1333 - '82947dda' => 1334 - array( 1335 - 0 => 'javelin-behavior', 1336 - 1 => 'javelin-stratcom', 1337 - 2 => 'javelin-workflow', 1338 - 3 => 'javelin-dom', 1339 - ), 1340 1333 '82f568cd' => 1341 1334 array( 1342 1335 0 => 'javelin-install', ··· 1971 1964 3 => 'phabricator-prefab', 1972 1965 4 => 'multirow-row-manager', 1973 1966 5 => 'javelin-json', 1967 + ), 1968 + 'fee00761' => 1969 + array( 1970 + 0 => 'javelin-behavior', 1971 + 1 => 'javelin-stratcom', 1972 + 2 => 'javelin-workflow', 1973 + 3 => 'javelin-dom', 1974 1974 ), 1975 1975 28497740 => 1976 1976 array(
+3 -2
src/applications/maniphest/config/PhabricatorManiphestConfigOptions.php
··· 149 149 - `default` This is the default status for newly created tasks. You must 150 150 designate one status as default, and it must be an open status. 151 151 - `closed` This is the default status for closed tasks (for example, tasks 152 - closed via the "!close" action in email). You must designate one status 153 - as the default closed status, and it must be a closed status. 152 + closed via the "!close" action in email or via the quick close button in 153 + Maniphest). You must designate one status as the default closed status, 154 + and it must be a closed status. 154 155 - `duplicate` This is the status used when tasks are merged into one 155 156 another as duplicates. You must designate one status for duplicates, 156 157 and it must be a closed status.
+24 -3
src/applications/maniphest/controller/ManiphestTaskDetailController.php
··· 208 208 209 209 $is_serious = PhabricatorEnv::getEnvConfig('phabricator.serious-business'); 210 210 211 + $submit_text = $is_serious 212 + ? pht('Submit') 213 + : pht('Avast!'); 214 + 215 + $close_text = $is_serious 216 + ? pht('Close Task') 217 + : pht('Scuttle Task'); 218 + 219 + $submit_control = id(new PHUIFormMultiSubmitControl()); 220 + if (!$task->isClosed()) { 221 + $close_image = id(new PHUIIconView()) 222 + ->setSpriteSheet(PHUIIconView::SPRITE_ICONS) 223 + ->setSpriteIcon('check'); 224 + $submit_control->addButtonView( 225 + id(new PHUIButtonView()) 226 + ->setColor(PHUIButtonView::GREY) 227 + ->setIcon($close_image) 228 + ->setText($close_text) 229 + ->setName('scuttle') 230 + ->addSigil('alternate-submit-button')); 231 + } 232 + $submit_control->addSubmitButton($submit_text); 233 + 211 234 $comment_form = new AphrontFormView(); 212 235 $comment_form 213 236 ->setUser($user) ··· 273 296 ->setValue($draft_text) 274 297 ->setID('transaction-comments') 275 298 ->setUser($user)) 276 - ->appendChild( 277 - id(new AphrontFormSubmitControl()) 278 - ->setValue($is_serious ? pht('Submit') : pht('Avast!'))); 299 + ->appendChild($submit_control); 279 300 280 301 $control_map = array( 281 302 ManiphestTransaction::TYPE_STATUS => 'resolution',
+31 -22
src/applications/maniphest/controller/ManiphestTransactionSaveController.php
··· 130 130 $transactions[] = $transaction; 131 131 } 132 132 133 + $resolution = $request->getStr('resolution'); 134 + $did_scuttle = false; 135 + if ($action !== ManiphestTransaction::TYPE_STATUS) { 136 + if ($request->getStr('scuttle')) { 137 + $transactions[] = id(new ManiphestTransaction()) 138 + ->setTransactionType(ManiphestTransaction::TYPE_STATUS) 139 + ->setNewValue(ManiphestTaskStatus::getDefaultClosedStatus()); 140 + $did_scuttle = true; 141 + $resolution = ManiphestTaskStatus::getDefaultClosedStatus(); 142 + } 143 + } 144 + 133 145 // When you interact with a task, we add you to the CC list so you get 134 146 // further updates, and possibly assign the task to you if you took an 135 147 // ownership action (closing it) but it's currently unowned. We also move ··· 137 149 // and create side-effect transactions for them. 138 150 139 151 $implicitly_claimed = false; 140 - switch ($action) { 141 - case ManiphestTransaction::TYPE_OWNER: 142 - if ($task->getOwnerPHID() == $transaction->getNewValue()) { 143 - // If this is actually no-op, don't generate the side effect. 144 - break; 145 - } 146 - // Otherwise, when a task is reassigned, move the previous owner to CC. 147 - $added_ccs[] = $task->getOwnerPHID(); 152 + if ($action == ManiphestTransaction::TYPE_OWNER) { 153 + if ($task->getOwnerPHID() == $transaction->getNewValue()) { 154 + // If this is actually no-op, don't generate the side effect. 148 155 break; 149 - case ManiphestTransaction::TYPE_STATUS: 150 - $resolution = $request->getStr('resolution'); 151 - if (!$task->getOwnerPHID() && 152 - ManiphestTaskStatus::isClosedStatus($resolution)) { 153 - // Closing an unassigned task. Assign the user as the owner of 154 - // this task. 155 - $assign = new ManiphestTransaction(); 156 - $assign->setTransactionType(ManiphestTransaction::TYPE_OWNER); 157 - $assign->setNewValue($user->getPHID()); 158 - $transactions[] = $assign; 156 + } 157 + // Otherwise, when a task is reassigned, move the previous owner to CC. 158 + $added_ccs[] = $task->getOwnerPHID(); 159 + } 159 160 160 - $implicitly_claimed = true; 161 - } 162 - break; 163 - } 161 + if ($did_scuttle || ($action == ManiphestTransaction::TYPE_STATUS)) { 162 + if (!$task->getOwnerPHID() && 163 + ManiphestTaskStatus::isClosedStatus($resolution)) { 164 + // Closing an unassigned task. Assign the user as the owner of 165 + // this task. 166 + $assign = new ManiphestTransaction(); 167 + $assign->setTransactionType(ManiphestTransaction::TYPE_OWNER); 168 + $assign->setNewValue($user->getPHID()); 169 + $transactions[] = $assign; 164 170 171 + $implicitly_claimed = true; 172 + } 173 + } 165 174 166 175 $user_owns_task = false; 167 176 if ($implicitly_claimed) {
+6 -2
src/view/form/control/AphrontFormSubmitControl.php
··· 2 2 3 3 final class AphrontFormSubmitControl extends AphrontFormControl { 4 4 5 - protected $cancelButton; 5 + private $cancelButton; 6 6 7 7 public function addCancelButton($href, $label = null) { 8 8 if (!$label) { ··· 35 35 ), 36 36 $this->getValue()); 37 37 } 38 - return hsprintf('%s%s', $submit_button, $this->cancelButton); 38 + 39 + return array( 40 + $submit_button, 41 + $this->cancelButton, 42 + ); 39 43 } 40 44 41 45 }
+7 -1
src/view/form/control/PHUIFormMultiSubmitControl.php
··· 31 31 return $this; 32 32 } 33 33 34 + public function addButtonView(PHUIButtonView $button) { 35 + $this->buttons[] = $button; 36 + return $this; 37 + } 38 + 34 39 public function addButton($name, $label, $class = null) { 35 - $this->buttons[] = phutil_tag( 40 + $this->buttons[] = javelin_tag( 36 41 'input', 37 42 array( 38 43 'type' => 'submit', 39 44 'name' => $name, 40 45 'value' => $label, 41 46 'class' => $class, 47 + 'sigil' => 'alternate-submit-button', 42 48 'disabled' => $this->getDisabled() ? 'disabled' : null, 43 49 )); 44 50 return $this;
+16 -3
src/view/phui/PHUIButtonView.php
··· 21 21 private $href = null; 22 22 private $title = null; 23 23 private $disabled; 24 + private $name; 25 + 26 + public function setName($name) { 27 + $this->name = $name; 28 + return $this; 29 + } 30 + 31 + public function getName() { 32 + return $this->name; 33 + } 24 34 25 35 public function setText($text) { 26 36 $this->text = $text; ··· 103 113 $classes[] = 'disabled'; 104 114 } 105 115 106 - return array('class' => $classes, 107 - 'href' => $this->href, 108 - 'title' => $this->title); 116 + return array( 117 + 'class' => $classes, 118 + 'href' => $this->href, 119 + 'name' => $this->name, 120 + 'title' => $this->title, 121 + ); 109 122 } 110 123 111 124 protected function getTagContent() {
+2 -1
webroot/rsrc/css/phui/phui-form-view.css
··· 108 108 } 109 109 110 110 .phui-form-control-multi-submit input, 111 + .phui-form-control-multi-submit button, 111 112 .phui-form-control-multi-submit a { 112 113 float: right; 113 - margin: 0.5em 0 0em 2%; 114 + margin: 4px 0 0 8px; 114 115 width: auto; 115 116 } 116 117
+20 -1
webroot/rsrc/js/core/behavior-workflow.js
··· 8 8 9 9 JX.behavior('workflow', function() { 10 10 11 + // If a user clicks an alternate submit button, make sure it gets marshalled 12 + // into the workflow. 13 + JX.Stratcom.listen( 14 + 'click', 15 + ['workflow', 'tag:form', 'alternate-submit-button'], 16 + function(e) { 17 + e.prevent(); 18 + 19 + var target = e.getNode('alternate-submit-button'); 20 + var form = e.getNode('tag:form'); 21 + var button = {}; 22 + button[target.name] = target.value || true; 23 + 24 + JX.DOM.invoke(form, 'didSyntheticSubmit', {extra: button}); 25 + }); 26 + 11 27 // Listen for both real and synthetic submit events. 12 28 JX.Stratcom.listen( 13 29 ['submit', 'didSyntheticSubmit'], ··· 17 33 return; 18 34 } 19 35 36 + var data = e.getData(); 37 + var extra = (data && data.extra) || {}; 38 + 20 39 // NOTE: We activate workflow if any parent node has the "workflow" sigil, 21 40 // not just the <form /> itself. 22 41 23 42 e.prevent(); 24 - JX.Workflow.newFromForm(e.getNode('tag:form')).start(); 43 + JX.Workflow.newFromForm(e.getNode('tag:form'), extra).start(); 25 44 }); 26 45 27 46 JX.Stratcom.listen(