diff --git a/src/applications/project/engine/PhabricatorProjectEditEngine.php b/src/applications/project/engine/PhabricatorProjectEditEngine.php --- a/src/applications/project/engine/PhabricatorProjectEditEngine.php +++ b/src/applications/project/engine/PhabricatorProjectEditEngine.php @@ -323,4 +323,62 @@ } + /** + * Create a button to copy the text description of the previous milestone to + * the clipboard, to make it a bit more convenient for project creators to + * have more consistency + * + * @return PHUIButtonView|null Button to copy the description + */ + protected function createMilestoneDescriptionCopyButton() { + $milestone = $this->getMilestoneProject(); + if ($milestone) { + $number = ($milestone->loadNextMilestoneNumber() - 1); + if ($number > 0) { + $previous_milestone = id(new PhabricatorProjectQuery()) + ->setViewer($this->getViewer()) + ->withParentProjectPHIDs(array($milestone->getPHID())) + ->withIsMilestone(true) + ->withMilestoneNumberBetween($number, $number) + ->executeOne(); + if ($previous_milestone) { + $desc_field = PhabricatorCustomField::getObjectField( + $previous_milestone, + PhabricatorCustomField::ROLE_VIEW, + 'std:project:internal:description'); + if ($desc_field) { + $viewer = $this->getViewer(); + $desc_field + ->setViewer($viewer) + ->readValueFromObject($previous_milestone); + id(new PhabricatorCustomFieldStorageQuery()) + ->addField($desc_field) + ->execute(); + if (phutil_nonempty_string($desc_field->getValueForStorage())) { + Javelin::initBehavior('phabricator-clipboard-copy'); + return id(new PHUIButtonView()) + ->setTag('a') + ->setColor(PHUIButtonView::GREY) + ->setText(pht('Copy Description of Previous Milestone to + Clipboard for Re-Use')) + ->setIcon('fa-clipboard') + ->setHref('#') + ->addSigil('clipboard-copy') + ->addSigil('has-tooltip') + ->setMetadata( + array( + 'tip' => null, + 'text' => $desc_field->getValueForStorage(), + 'successMessage' => pht('Description of previous milestone + copied to clipboard.'), + 'errorMessage' => pht('Copying failed.'), + )); + } + } + } + } + } + return null; + } + } diff --git a/src/applications/transactions/editengine/PhabricatorEditEngine.php b/src/applications/transactions/editengine/PhabricatorEditEngine.php --- a/src/applications/transactions/editengine/PhabricatorEditEngine.php +++ b/src/applications/transactions/editengine/PhabricatorEditEngine.php @@ -1396,7 +1396,12 @@ $field->appendToForm($form); } + $copy_milestone_desc = null; if ($this->getIsCreate()) { + // TODO: Have a getAdditionalFormButtons abstraction not to check class? + if (get_class($this) === 'PhabricatorProjectEditEngine') { + $copy_milestone_desc = $this->createMilestoneDescriptionCopyButton(); + } $cancel_uri = $this->getObjectCreateCancelURI($object); $submit_button = $this->getObjectCreateButtonText($object); } else { @@ -1412,6 +1417,10 @@ $buttons->addCancelButton($cancel_uri); } + if ($copy_milestone_desc) { + $buttons->addButton($copy_milestone_desc); + } + $form->appendControl($buttons); }