diff --git a/resources/sql/autopatches/20150620.diviner.status.sql b/resources/sql/autopatches/20150620.diviner.status.sql new file mode 100644 --- /dev/null +++ b/resources/sql/autopatches/20150620.diviner.status.sql @@ -0,0 +1,2 @@ +ALTER TABLE {$NAMESPACE}_diviner.diviner_livebook + ADD COLUMN isArchived BOOL NOT NULL AFTER repositoryPHID; diff --git a/src/__phutil_library_map__.php b/src/__phutil_library_map__.php --- a/src/__phutil_library_map__.php +++ b/src/__phutil_library_map__.php @@ -648,6 +648,7 @@ 'DivinerAtomSearchIndexer' => 'applications/diviner/search/DivinerAtomSearchIndexer.php', 'DivinerAtomizeWorkflow' => 'applications/diviner/workflow/DivinerAtomizeWorkflow.php', 'DivinerAtomizer' => 'applications/diviner/atomizer/DivinerAtomizer.php', + 'DivinerBookArchiveController' => 'applications/diviner/controller/DivinerBookArchiveController.php', 'DivinerBookController' => 'applications/diviner/controller/DivinerBookController.php', 'DivinerBookDatasource' => 'applications/diviner/typeahead/DivinerBookDatasource.php', 'DivinerBookEditController' => 'applications/diviner/controller/DivinerBookEditController.php', @@ -4016,6 +4017,7 @@ 'DivinerAtomSearchIndexer' => 'PhabricatorSearchDocumentIndexer', 'DivinerAtomizeWorkflow' => 'DivinerWorkflow', 'DivinerAtomizer' => 'Phobject', + 'DivinerBookArchiveController' => 'DivinerController', 'DivinerBookController' => 'DivinerController', 'DivinerBookDatasource' => 'PhabricatorTypeaheadDatasource', 'DivinerBookEditController' => 'DivinerController', diff --git a/src/applications/diviner/application/PhabricatorDivinerApplication.php b/src/applications/diviner/application/PhabricatorDivinerApplication.php --- a/src/applications/diviner/application/PhabricatorDivinerApplication.php +++ b/src/applications/diviner/application/PhabricatorDivinerApplication.php @@ -39,6 +39,7 @@ 'find/' => 'DivinerFindController', ), '/book/(?P[^/]+)/' => 'DivinerBookController', + '/book/(?P[^/]+)/archive/' => 'DivinerBookArchiveController', '/book/(?P[^/]+)/edit/' => 'DivinerBookEditController', '/book/'. '(?P[^/]+)/'. diff --git a/src/applications/diviner/controller/DivinerBookArchiveController.php b/src/applications/diviner/controller/DivinerBookArchiveController.php new file mode 100644 --- /dev/null +++ b/src/applications/diviner/controller/DivinerBookArchiveController.php @@ -0,0 +1,67 @@ +getViewer(); + + $book = id(new DivinerBookQuery()) + ->setViewer($viewer) + ->requireCapabilities( + array( + PhabricatorPolicyCapability::CAN_VIEW, + PhabricatorPolicyCapability::CAN_EDIT, + )) + ->withNames(array($request->getURIData('book'))) + ->executeOne(); + + if (!$book) { + return new Aphront404Response(); + } + + $view_uri = '/book/'.$book->getName().'/'; + + if ($request->isFormPost()) { + if ($book->getIsArchived()) { + $is_archived = false; + } else { + $is_archived = true; + } + + $xactions = array(); + + $xactions[] = id(new DivinerLiveBookTransaction()) + ->setTransactionType(DivinerLiveBookTransaction::TYPE_ARCHIVED) + ->setNewValue($is_archived); + + id(new DivinerLiveBookEditor()) + ->setActor($viewer) + ->setContentSourceFromRequest($request) + ->setContinueOnNoEffect(true) + ->setContinueOnMissingFields(true) + ->applyTransactions($book, $xactions); + + return id(new AphrontRedirectResponse())->setURI($view_uri); + } + + if ($book->getIsArchived()) { + $title = pht('Really activate book?'); + $body = pht('This book will become active again.'); + $button = pht('Activate Book'); + } else { + $title = pht('Really archive book?'); + $body = pht('This book will be moved to the archive.'); + $button = pht('Archive Book'); + } + + $dialog = id(new AphrontDialogView()) + ->setUser($viewer) + ->setTitle($title) + ->appendChild($body) + ->addCancelButton($view_uri) + ->addSubmitButton($button); + + return id(new AphrontDialogResponse())->setDialog($dialog); + } + +} diff --git a/src/applications/diviner/controller/DivinerBookController.php b/src/applications/diviner/controller/DivinerBookController.php --- a/src/applications/diviner/controller/DivinerBookController.php +++ b/src/applications/diviner/controller/DivinerBookController.php @@ -53,6 +53,12 @@ ->setName($book->getRepository()->getMonogram())); } + if ($book->getIsArchived()) { + $header->setStatus('fa-ban', 'red', pht('Archived')); + } else { + $header->setStatus('fa-check', 'bluegrey', pht('Active')); + } + $document = new PHUIDocumentView(); $document->setHeader($header); $document->addClass('diviner-view'); @@ -136,6 +142,24 @@ ->setHref('/book/'.$book->getName().'/edit/') ->setDisabled(!$can_edit)); + if ($book->getIsArchived()) { + $action_view->addAction( + id(new PhabricatorActionView()) + ->setName(pht('Activate Book')) + ->setIcon('fa-check') + ->setHref('/book/'.$book->getName().'/archive/') + ->setDisabled(!$can_edit) + ->setWorkflow(true)); + } else { + $action_view->addAction( + id(new PhabricatorActionView()) + ->setName(pht('Archive Book')) + ->setIcon('fa-ban') + ->setHref('/book/'.$book->getName().'/archive/') + ->setDisabled(!$can_edit) + ->setWorkflow(true)); + } + return $action_view; } diff --git a/src/applications/diviner/editor/DivinerLiveBookEditor.php b/src/applications/diviner/editor/DivinerLiveBookEditor.php --- a/src/applications/diviner/editor/DivinerLiveBookEditor.php +++ b/src/applications/diviner/editor/DivinerLiveBookEditor.php @@ -17,7 +17,61 @@ $types[] = PhabricatorTransactions::TYPE_VIEW_POLICY; $types[] = PhabricatorTransactions::TYPE_EDIT_POLICY; + $types[] = DivinerLiveBookTransaction::TYPE_ARCHIVED; + return $types; } + protected function getCustomTransactionOldValue( + PhabricatorLiskDAO $object, + PhabricatorApplicationTransaction $xaction) { + + switch ($xaction->getTransactionType()) { + case DivinerLiveBookTransaction::TYPE_ARCHIVED: + return $object->getIsArchived(); + default: + return parent::getCustomTransactionOldValue($object, $xaction); + } + } + + protected function getCustomTransactionNewValue( + PhabricatorLiskDAO $object, + PhabricatorApplicationTransaction $xaction) { + + switch ($xaction->getTransactionType()) { + case DivinerLiveBookTransaction::TYPE_ARCHIVED: + return $xaction->getNewValue(); + default: + return parent::getCustomTransactionNewValue($object, $xaction); + } + } + + protected function applyCustomInternalTransaction( + PhabricatorLiskDAO $object, + PhabricatorApplicationTransaction $xaction) { + + switch ($xaction->getTransactionType()) { + case DivinerLiveBookTransaction::TYPE_ARCHIVED: + $object->setIsArchived((bool)$xaction->getNewValue()); + return; + default: + return parent::applyCustomInternalTransaction($object, $xaction); + } + } + + protected function applyCustomExternalTransaction( + PhabricatorLiskDAO $object, + PhabricatorApplicationTransaction $xaction) { + + $old = $xaction->getOldValue(); + $new = $xaction->getNewValue(); + + switch ($xaction->getTransactionType()) { + case DivinerLiveBookTransaction::TYPE_ARCHIVED: + return; + default: + return parent::applyCustomExternalTransaction($object, $xaction); + } + } + } diff --git a/src/applications/diviner/storage/DivinerLiveBook.php b/src/applications/diviner/storage/DivinerLiveBook.php --- a/src/applications/diviner/storage/DivinerLiveBook.php +++ b/src/applications/diviner/storage/DivinerLiveBook.php @@ -9,6 +9,7 @@ protected $name; protected $repositoryPHID; + protected $isArchived = false; protected $viewPolicy; protected $editPolicy; protected $configurationData = array(); diff --git a/src/applications/diviner/storage/DivinerLiveBookTransaction.php b/src/applications/diviner/storage/DivinerLiveBookTransaction.php --- a/src/applications/diviner/storage/DivinerLiveBookTransaction.php +++ b/src/applications/diviner/storage/DivinerLiveBookTransaction.php @@ -3,6 +3,8 @@ final class DivinerLiveBookTransaction extends PhabricatorApplicationTransaction { + const TYPE_ARCHIVED = 'diviner:book:archived'; + public function getApplicationName() { return 'diviner'; } @@ -15,4 +17,86 @@ return null; } + public function getColor() { + $old = $this->getOldValue(); + $new = $this->getNewValue(); + + switch ($this->getTransactionType()) { + case self::TYPE_ARCHIVED: + if ($new) { + return 'red'; + } else { + return 'green'; + } + default: + return parent::getColor(); + } + } + + public function getIcon() { + $old = $this->getOldValue(); + $new = $this->getNewValue(); + + switch ($this->getTransactionType()) { + case self::TYPE_ARCHIVED: + if ($new) { + return 'fa-ban'; + } else { + return 'fa-check'; + } + default: + return parent::getIcon(); + } + } + + public function getTitle() { + $old = $this->getOldValue(); + $new = $this->getNewValue(); + $author_handle = $this->renderHandleLink($this->getAuthorPHID()); + + switch ($this->getTransactionType()) { + case self::TYPE_ARCHIVED: + if ($new) { + return pht( + '%s archived this book.', + $author_handle); + } else { + return pht( + '%s activated this book.', + $author_handle); + } + break; + + default: + return parent::getTitle(); + } + } + + public function getTitleForFeed() { + $author_phid = $this->getAuthorPHID(); + $object_phid = $this->getObjectPHID(); + $author_handle = $this->renderHandleLink($author_phid); + $object_handle = $this->renderHandleLink($object_phid); + + $old = $this->getOldValue(); + $new = $this->getNewValue(); + + switch ($this->getTransactionType()) { + case self::TYPE_ARCHIVED: + if ($new) { + return pht( + '%s archived %s.', + $author_handle, + $object_handle); + } else { + return pht( + '%s activated %s.', + $author_handle, + $object_handle); + } + default: + return parent::getTitleForFeed(); + } + } + }