diff --git a/resources/celerity/map.php b/resources/celerity/map.php index 1b4fd3517a..720683c371 100644 --- a/resources/celerity/map.php +++ b/resources/celerity/map.php @@ -9,7 +9,7 @@ return array( 'names' => array( 'conpherence.pkg.css' => 'e68cf1fa', 'conpherence.pkg.js' => '15191c65', - 'core.pkg.css' => 'badf3f16', + 'core.pkg.css' => '2574c199', 'core.pkg.js' => 'b5a949ca', 'differential.pkg.css' => '06dc617c', 'differential.pkg.js' => 'c1cfa143', @@ -122,7 +122,7 @@ return array( 'rsrc/css/layout/phabricator-source-code-view.css' => '2ab25dfa', 'rsrc/css/phui/button/phui-button-bar.css' => 'f1ff5494', 'rsrc/css/phui/button/phui-button-simple.css' => '8e1baf68', - 'rsrc/css/phui/button/phui-button.css' => '1863cc6e', + 'rsrc/css/phui/button/phui-button.css' => '6ccb303c', 'rsrc/css/phui/calendar/phui-calendar-day.css' => '572b1893', 'rsrc/css/phui/calendar/phui-calendar-list.css' => '576be600', 'rsrc/css/phui/calendar/phui-calendar-month.css' => '21154caf', @@ -151,7 +151,7 @@ return array( 'rsrc/css/phui/phui-document.css' => 'c4ac41f9', 'rsrc/css/phui/phui-feed-story.css' => '44a9c8e9', 'rsrc/css/phui/phui-fontkit.css' => '1320ed01', - 'rsrc/css/phui/phui-form-view.css' => 'f808e5be', + 'rsrc/css/phui/phui-form-view.css' => '2f43fae7', 'rsrc/css/phui/phui-form.css' => '7aaa04e3', 'rsrc/css/phui/phui-head-thing.css' => 'fd311e5f', 'rsrc/css/phui/phui-header-view.css' => '1ba8b707', @@ -800,7 +800,7 @@ return array( 'phui-box-css' => '4bd6cdb9', 'phui-bulk-editor-css' => '9a81e5d5', 'phui-button-bar-css' => 'f1ff5494', - 'phui-button-css' => '1863cc6e', + 'phui-button-css' => '6ccb303c', 'phui-button-simple-css' => '8e1baf68', 'phui-calendar-css' => 'f1ddf11c', 'phui-calendar-day-css' => '572b1893', @@ -819,7 +819,7 @@ return array( 'phui-font-icon-base-css' => '870a7360', 'phui-fontkit-css' => '1320ed01', 'phui-form-css' => '7aaa04e3', - 'phui-form-view-css' => 'f808e5be', + 'phui-form-view-css' => '2f43fae7', 'phui-head-thing-view-css' => 'fd311e5f', 'phui-header-view-css' => '1ba8b707', 'phui-hovercard' => '1bd28176', diff --git a/src/__phutil_library_map__.php b/src/__phutil_library_map__.php index e6146bc9ef..c25019b1fb 100644 --- a/src/__phutil_library_map__.php +++ b/src/__phutil_library_map__.php @@ -5021,7 +5021,9 @@ phutil_register_library_map(array( 'PhrictionDocumentController' => 'applications/phriction/controller/PhrictionDocumentController.php', 'PhrictionDocumentDatasource' => 'applications/phriction/typeahead/PhrictionDocumentDatasource.php', 'PhrictionDocumentDeleteTransaction' => 'applications/phriction/xaction/PhrictionDocumentDeleteTransaction.php', + 'PhrictionDocumentDraftTransaction' => 'applications/phriction/xaction/PhrictionDocumentDraftTransaction.php', 'PhrictionDocumentEditEngine' => 'applications/phriction/editor/PhrictionDocumentEditEngine.php', + 'PhrictionDocumentEditTransaction' => 'applications/phriction/xaction/PhrictionDocumentEditTransaction.php', 'PhrictionDocumentFerretEngine' => 'applications/phriction/search/PhrictionDocumentFerretEngine.php', 'PhrictionDocumentFulltextEngine' => 'applications/phriction/search/PhrictionDocumentFulltextEngine.php', 'PhrictionDocumentHeraldAdapter' => 'applications/phriction/herald/PhrictionDocumentHeraldAdapter.php', @@ -11138,11 +11140,13 @@ phutil_register_library_map(array( ), 'PhrictionDocumentAuthorHeraldField' => 'PhrictionDocumentHeraldField', 'PhrictionDocumentContentHeraldField' => 'PhrictionDocumentHeraldField', - 'PhrictionDocumentContentTransaction' => 'PhrictionDocumentVersionTransaction', + 'PhrictionDocumentContentTransaction' => 'PhrictionDocumentEditTransaction', 'PhrictionDocumentController' => 'PhrictionController', 'PhrictionDocumentDatasource' => 'PhabricatorTypeaheadDatasource', 'PhrictionDocumentDeleteTransaction' => 'PhrictionDocumentVersionTransaction', + 'PhrictionDocumentDraftTransaction' => 'PhrictionDocumentEditTransaction', 'PhrictionDocumentEditEngine' => 'PhabricatorEditEngine', + 'PhrictionDocumentEditTransaction' => 'PhrictionDocumentVersionTransaction', 'PhrictionDocumentFerretEngine' => 'PhabricatorFerretEngine', 'PhrictionDocumentFulltextEngine' => 'PhabricatorFulltextEngine', 'PhrictionDocumentHeraldAdapter' => 'HeraldAdapter', diff --git a/src/applications/phriction/controller/PhrictionDocumentController.php b/src/applications/phriction/controller/PhrictionDocumentController.php index d4c9d0b263..e424a7f148 100644 --- a/src/applications/phriction/controller/PhrictionDocumentController.php +++ b/src/applications/phriction/controller/PhrictionDocumentController.php @@ -450,19 +450,28 @@ final class PhrictionDocumentController $publish_name = pht('Publish Revert'); } + // If you're looking at the current version; and it's an unpublished + // draft; and you can publish it, add a UI hint that this might be an + // interesting action to take. + $hint_publish = false; + if ($is_draft) { + if ($can_publish) { + if ($document->getMaxVersion() == $content->getVersion()) { + $hint_publish = true; + } + } + } + $publish_uri = "/phriction/publish/{$id}/{$content_id}/"; - if (PhabricatorEnv::getEnvConfig('phabricator.show-prototypes')) { - $publish_name = pht('Publish (Prototype!)'); - - $curtain->addAction( - id(new PhabricatorActionView()) - ->setName($publish_name) - ->setIcon('fa-upload') - ->setDisabled(!$can_publish) - ->setWorkflow(true) - ->setHref($publish_uri)); - } + $curtain->addAction( + id(new PhabricatorActionView()) + ->setName($publish_name) + ->setIcon('fa-upload') + ->setSelected($hint_publish) + ->setDisabled(!$can_publish) + ->setWorkflow(true) + ->setHref($publish_uri)); if ($document->getStatus() == PhrictionDocumentStatus::STATUS_EXISTS) { $curtain->addAction( diff --git a/src/applications/phriction/controller/PhrictionEditController.php b/src/applications/phriction/controller/PhrictionEditController.php index 4c1d69c272..31879632de 100644 --- a/src/applications/phriction/controller/PhrictionEditController.php +++ b/src/applications/phriction/controller/PhrictionEditController.php @@ -95,8 +95,10 @@ final class PhrictionEditController $v_space = $document->getSpacePHID(); $content_text = $content->getContent(); + $is_draft_mode = ($document->getContent()->getVersion() != $max_version); if ($request->isFormPost()) { + $save_as_draft = ($is_draft_mode || $request->getExists('draft')); $title = $request->getStr('title'); $content_text = $request->getStr('content'); @@ -108,13 +110,18 @@ final class PhrictionEditController $v_projects = $request->getArr('projects'); $v_space = $request->getStr('spacePHID'); + if ($save_as_draft) { + $edit_type = PhrictionDocumentDraftTransaction::TRANSACTIONTYPE; + } else { + $edit_type = PhrictionDocumentContentTransaction::TRANSACTIONTYPE; + } + $xactions = array(); $xactions[] = id(new PhrictionTransaction()) ->setTransactionType(PhrictionDocumentTitleTransaction::TRANSACTIONTYPE) ->setNewValue($title); $xactions[] = id(new PhrictionTransaction()) - ->setTransactionType( - PhrictionDocumentContentTransaction::TRANSACTIONTYPE) + ->setTransactionType($edit_type) ->setNewValue($content_text); $xactions[] = id(new PhrictionTransaction()) ->setTransactionType(PhabricatorTransactions::TYPE_VIEW_POLICY) @@ -147,6 +154,14 @@ final class PhrictionEditController $editor->applyTransactions($document, $xactions); $uri = PhrictionDocument::getSlugURI($document->getSlug()); + $uri = new PhutilURI($uri); + + // If the user clicked "Save as Draft", take them to the draft, not + // to the current published page. + if ($save_as_draft) { + $uri = $uri->alter('v', $document->getMaxVersion()); + } + return id(new AphrontRedirectResponse())->setURI($uri); } catch (PhabricatorApplicationTransactionValidationException $ex) { $validation_exception = $ex; @@ -176,7 +191,7 @@ final class PhrictionEditController if ($overwrite) { $submit_button = pht('Overwrite Changes'); } else { - $submit_button = pht('Save Changes'); + $submit_button = pht('Save and Publish'); } } else { $submit_button = pht('Create Document'); @@ -196,7 +211,6 @@ final class PhrictionEditController $view_capability = PhabricatorPolicyCapability::CAN_VIEW; $edit_capability = PhabricatorPolicyCapability::CAN_EDIT; - $form = id(new AphrontFormView()) ->setUser($viewer) ->addHiddenInput('slug', $document->getSlug()) @@ -253,11 +267,26 @@ final class PhrictionEditController ->setLabel(pht('Edit Notes')) ->setValue($notes) ->setError(null) - ->setName('description')) - ->appendChild( + ->setName('description')); + + if ($is_draft_mode) { + $form->appendControl( id(new AphrontFormSubmitControl()) + ->addCancelButton($cancel_uri) + ->setValue(pht('Save Draft'))); + } else { + $draft_button = id(new PHUIButtonView()) + ->setTag('input') + ->setName('draft') + ->setText(pht('Save as Draft')) + ->setColor(PHUIButtonView::GREEN); + + $form->appendControl( + id(new AphrontFormSubmitControl()) + ->addButton($draft_button) ->addCancelButton($cancel_uri) ->setValue($submit_button)); + } $form_box = id(new PHUIObjectBoxView()) ->setHeaderText($page_title) diff --git a/src/applications/phriction/editor/PhrictionTransactionEditor.php b/src/applications/phriction/editor/PhrictionTransactionEditor.php index 3c045e16ba..6d72fc5b8e 100644 --- a/src/applications/phriction/editor/PhrictionTransactionEditor.php +++ b/src/applications/phriction/editor/PhrictionTransactionEditor.php @@ -74,6 +74,21 @@ final class PhrictionTransactionEditor return $this; } + public function setShouldPublishContent( + PhrictionDocument $object, + $publish) { + + if ($publish) { + $content_phid = $this->getNewContent()->getPHID(); + } else { + $content_phid = $this->getOldContent()->getPHID(); + } + + $object->setContentPHID($content_phid); + + return $this; + } + public function getEditorApplicationClass() { return 'PhabricatorPhrictionApplication'; } diff --git a/src/applications/phriction/xaction/PhrictionDocumentContentTransaction.php b/src/applications/phriction/xaction/PhrictionDocumentContentTransaction.php index 759121dd65..de6d92aac6 100644 --- a/src/applications/phriction/xaction/PhrictionDocumentContentTransaction.php +++ b/src/applications/phriction/xaction/PhrictionDocumentContentTransaction.php @@ -1,94 +1,16 @@ getEditor()->getIsNewObject()) { - return null; - } - return $object->getContent()->getContent(); - } - - public function generateNewValue($object, $value) { - return $value; - } - public function applyInternalEffects($object, $value) { + parent::applyInternalEffects($object, $value); + $object->setStatus(PhrictionDocumentStatus::STATUS_EXISTS); - $content = $this->getNewDocumentContent($object); - $content->setContent($value); - } - - public function shouldHide() { - if ($this->getOldValue() === null) { - return true; - } else { - return false; - } - } - - public function getActionStrength() { - return 1.3; - } - - public function getActionName() { - return pht('Edited'); - } - - public function getTitle() { - return pht( - '%s edited the content of this document.', - $this->renderAuthor()); - } - - public function getTitleForFeed() { - return pht( - '%s edited the content of %s.', - $this->renderAuthor(), - $this->renderObject()); - } - - public function hasChangeDetailView() { - return true; - } - - public function getMailDiffSectionHeader() { - return pht('CHANGES TO DOCUMENT CONTENT'); - } - - public function newChangeDetailView() { - $viewer = $this->getViewer(); - - return id(new PhabricatorApplicationTransactionTextDiffDetailView()) - ->setViewer($viewer) - ->setOldText($this->getOldValue()) - ->setNewText($this->getNewValue()); - } - - public function newRemarkupChanges() { - $changes = array(); - - $changes[] = $this->newRemarkupChange() - ->setOldValue($this->getOldValue()) - ->setNewValue($this->getNewValue()); - - return $changes; - } - - public function validateTransactions($object, array $xactions) { - $errors = array(); - - $content = $object->getContent()->getContent(); - if ($this->isEmptyTextTransaction($content, $xactions)) { - $errors[] = $this->newRequiredError( - pht('Documents must have content.')); - } - - return $errors; + $this->getEditor()->setShouldPublishContent($object, true); } } diff --git a/src/applications/phriction/xaction/PhrictionDocumentDraftTransaction.php b/src/applications/phriction/xaction/PhrictionDocumentDraftTransaction.php new file mode 100644 index 0000000000..91a4b4ade5 --- /dev/null +++ b/src/applications/phriction/xaction/PhrictionDocumentDraftTransaction.php @@ -0,0 +1,14 @@ +getEditor()->setShouldPublishContent($object, false); + } + +} diff --git a/src/applications/phriction/xaction/PhrictionDocumentEditTransaction.php b/src/applications/phriction/xaction/PhrictionDocumentEditTransaction.php new file mode 100644 index 0000000000..551e8c8c2a --- /dev/null +++ b/src/applications/phriction/xaction/PhrictionDocumentEditTransaction.php @@ -0,0 +1,95 @@ +getEditor()->getIsNewObject()) { + return null; + } + + // NOTE: We want to get the newest version of the content here, regardless + // of whether it's published or not. + + $actor = $this->getActor(); + + return id(new PhrictionContentQuery()) + ->setViewer($actor) + ->withDocumentPHIDs(array($object->getPHID())) + ->setOrder('newest') + ->setLimit(1) + ->executeOne() + ->getContent(); + } + + public function generateNewValue($object, $value) { + return $value; + } + + public function applyInternalEffects($object, $value) { + $content = $this->getNewDocumentContent($object); + $content->setContent($value); + } + + public function getActionStrength() { + return 1.3; + } + + public function getActionName() { + return pht('Edited'); + } + + public function getTitle() { + return pht( + '%s edited the content of this document.', + $this->renderAuthor()); + } + + public function getTitleForFeed() { + return pht( + '%s edited the content of %s.', + $this->renderAuthor(), + $this->renderObject()); + } + + public function getMailDiffSectionHeader() { + return pht('CHANGES TO DOCUMENT CONTENT'); + } + + public function hasChangeDetailView() { + return true; + } + + public function newChangeDetailView() { + $viewer = $this->getViewer(); + + return id(new PhabricatorApplicationTransactionTextDiffDetailView()) + ->setViewer($viewer) + ->setOldText($this->getOldValue()) + ->setNewText($this->getNewValue()); + } + + public function newRemarkupChanges() { + $changes = array(); + + $changes[] = $this->newRemarkupChange() + ->setOldValue($this->getOldValue()) + ->setNewValue($this->getNewValue()); + + return $changes; + } + + public function validateTransactions($object, array $xactions) { + $errors = array(); + + $content = $object->getContent()->getContent(); + if ($this->isEmptyTextTransaction($content, $xactions)) { + $errors[] = $this->newRequiredError( + pht('Documents must have content.')); + } + + return $errors; + } + + +} diff --git a/src/view/phui/PHUIButtonView.php b/src/view/phui/PHUIButtonView.php index bad24122bc..2231649f12 100644 --- a/src/view/phui/PHUIButtonView.php +++ b/src/view/phui/PHUIButtonView.php @@ -233,14 +233,15 @@ final class PHUIButtonView extends AphrontTagView { $classes = array(); } - // See PHI823. If we aren't rendering a "