diff --git a/resources/sql/autopatches/20140629.dasharchive.1.sql b/resources/sql/autopatches/20140629.dasharchive.1.sql new file mode 100644 index 0000000000..e6a10594aa --- /dev/null +++ b/resources/sql/autopatches/20140629.dasharchive.1.sql @@ -0,0 +1,2 @@ +ALTER TABLE {$NAMESPACE}_dashboard.dashboard_panel + ADD isArchived BOOL NOT NULL DEFAULT 0 AFTER editPolicy; diff --git a/src/__phutil_library_map__.php b/src/__phutil_library_map__.php index 9ab1c176e3..da9ae3416d 100644 --- a/src/__phutil_library_map__.php +++ b/src/__phutil_library_map__.php @@ -1499,6 +1499,7 @@ phutil_register_library_map(array( 'PhabricatorDashboardPHIDTypeDashboard' => 'applications/dashboard/phid/PhabricatorDashboardPHIDTypeDashboard.php', 'PhabricatorDashboardPHIDTypePanel' => 'applications/dashboard/phid/PhabricatorDashboardPHIDTypePanel.php', 'PhabricatorDashboardPanel' => 'applications/dashboard/storage/PhabricatorDashboardPanel.php', + 'PhabricatorDashboardPanelArchiveController' => 'applications/dashboard/controller/PhabricatorDashboardPanelArchiveController.php', 'PhabricatorDashboardPanelCoreCustomField' => 'applications/dashboard/customfield/PhabricatorDashboardPanelCoreCustomField.php', 'PhabricatorDashboardPanelCustomField' => 'applications/dashboard/customfield/PhabricatorDashboardPanelCustomField.php', 'PhabricatorDashboardPanelEditController' => 'applications/dashboard/controller/PhabricatorDashboardPanelEditController.php', @@ -4334,6 +4335,7 @@ phutil_register_library_map(array( 1 => 'PhabricatorPolicyInterface', 2 => 'PhabricatorCustomFieldInterface', ), + 'PhabricatorDashboardPanelArchiveController' => 'PhabricatorDashboardController', 'PhabricatorDashboardPanelCoreCustomField' => array( 0 => 'PhabricatorDashboardPanelCustomField', diff --git a/src/applications/dashboard/application/PhabricatorApplicationDashboard.php b/src/applications/dashboard/application/PhabricatorApplicationDashboard.php index a3eaab97bc..ad0e39e6ea 100644 --- a/src/applications/dashboard/application/PhabricatorApplicationDashboard.php +++ b/src/applications/dashboard/application/PhabricatorApplicationDashboard.php @@ -42,6 +42,8 @@ final class PhabricatorApplicationDashboard extends PhabricatorApplication { 'create/' => 'PhabricatorDashboardPanelEditController', 'edit/(?:(?P\d+)/)?' => 'PhabricatorDashboardPanelEditController', 'render/(?P\d+)/' => 'PhabricatorDashboardPanelRenderController', + 'archive/(?P\d+)/' => + 'PhabricatorDashboardPanelArchiveController', ), ), ); diff --git a/src/applications/dashboard/controller/PhabricatorDashboardAddPanelController.php b/src/applications/dashboard/controller/PhabricatorDashboardAddPanelController.php index 28c987fa37..ceeeb1fc5c 100644 --- a/src/applications/dashboard/controller/PhabricatorDashboardAddPanelController.php +++ b/src/applications/dashboard/controller/PhabricatorDashboardAddPanelController.php @@ -60,6 +60,7 @@ final class PhabricatorDashboardAddPanelController $panels = id(new PhabricatorDashboardPanelQuery()) ->setViewer($viewer) + ->withArchived(false) ->execute(); if (!$panels) { diff --git a/src/applications/dashboard/controller/PhabricatorDashboardPanelArchiveController.php b/src/applications/dashboard/controller/PhabricatorDashboardPanelArchiveController.php new file mode 100644 index 0000000000..8f819d7a37 --- /dev/null +++ b/src/applications/dashboard/controller/PhabricatorDashboardPanelArchiveController.php @@ -0,0 +1,66 @@ +id = $data['id']; + } + + public function processRequest() { + $request = $this->getRequest(); + $viewer = $request->getUser(); + + $panel = id(new PhabricatorDashboardPanelQuery()) + ->setViewer($viewer) + ->withIDs(array($this->id)) + ->requireCapabilities( + array( + PhabricatorPolicyCapability::CAN_VIEW, + PhabricatorPolicyCapability::CAN_EDIT, + )) + ->executeOne(); + if (!$panel) { + return new Aphront404Response(); + } + + $next_uri = '/'.$panel->getMonogram(); + + if ($request->isFormPost()) { + $xactions = array(); + $xactions[] = id(new PhabricatorDashboardPanelTransaction()) + ->setTransactionType(PhabricatorDashboardPanelTransaction::TYPE_ARCHIVE) + ->setNewValue((int)!$panel->getIsArchived()); + + id(new PhabricatorDashboardPanelTransactionEditor()) + ->setActor($viewer) + ->setContentSourceFromRequest($request) + ->applyTransactions($panel, $xactions); + + return id(new AphrontRedirectResponse())->setURI($next_uri); + } + + if ($panel->getIsArchived()) { + $title = pht('Activate Panel?'); + $body = pht( + 'This panel will be reactivated and appear in other interfaces as '. + 'an active panel.'); + $submit_text = pht('Activate Panel'); + } else { + $title = pht('Archive Panel?'); + $body = pht( + 'This panel will be archived and no longer appear in lists of active '. + 'panels.'); + $submit_text = pht('Archive Panel'); + } + + return $this->newDialog() + ->setTitle($title) + ->appendParagraph($body) + ->addSubmitButton($submit_text) + ->addCancelButton($next_uri); + } + +} diff --git a/src/applications/dashboard/controller/PhabricatorDashboardPanelViewController.php b/src/applications/dashboard/controller/PhabricatorDashboardPanelViewController.php index 09f8ac584e..dd594d01b7 100644 --- a/src/applications/dashboard/controller/PhabricatorDashboardPanelViewController.php +++ b/src/applications/dashboard/controller/PhabricatorDashboardPanelViewController.php @@ -96,6 +96,22 @@ final class PhabricatorDashboardPanelViewController ->setDisabled(!$can_edit) ->setWorkflow(!$can_edit)); + if (!$panel->getIsArchived()) { + $archive_text = pht('Archive Panel'); + $archive_icon = 'fa-times'; + } else { + $archive_text = pht('Activate Panel'); + $archive_icon = 'fa-plus'; + } + + $actions->addAction( + id(new PhabricatorActionView()) + ->setName($archive_text) + ->setIcon($archive_icon) + ->setHref($this->getApplicationURI("panel/archive/{$id}/")) + ->setDisabled(!$can_edit) + ->setWorkflow(true)); + $actions->addAction( id(new PhabricatorActionView()) ->setName(pht('View Standalone')) diff --git a/src/applications/dashboard/customfield/PhabricatorDashboardPanelTabsCustomField.php b/src/applications/dashboard/customfield/PhabricatorDashboardPanelTabsCustomField.php index 7892a51e60..f473b3f6cd 100644 --- a/src/applications/dashboard/customfield/PhabricatorDashboardPanelTabsCustomField.php +++ b/src/applications/dashboard/customfield/PhabricatorDashboardPanelTabsCustomField.php @@ -30,6 +30,10 @@ final class PhabricatorDashboardPanelTabsCustomField } public function renderEditControl(array $handles) { + // NOTE: This includes archived panels so we don't mutate the tabs + // when saving a tab panel that includes archied panels. This whole UI is + // hopefully temporary anyway. + $panels = id(new PhabricatorDashboardPanelQuery()) ->setViewer($this->getViewer()) ->execute(); diff --git a/src/applications/dashboard/editor/PhabricatorDashboardPanelTransactionEditor.php b/src/applications/dashboard/editor/PhabricatorDashboardPanelTransactionEditor.php index de1299024d..c1ed4d2115 100644 --- a/src/applications/dashboard/editor/PhabricatorDashboardPanelTransactionEditor.php +++ b/src/applications/dashboard/editor/PhabricatorDashboardPanelTransactionEditor.php @@ -11,6 +11,7 @@ final class PhabricatorDashboardPanelTransactionEditor $types[] = PhabricatorTransactions::TYPE_EDGE; $types[] = PhabricatorDashboardPanelTransaction::TYPE_NAME; + $types[] = PhabricatorDashboardPanelTransaction::TYPE_ARCHIVE; return $types; } @@ -24,6 +25,8 @@ final class PhabricatorDashboardPanelTransactionEditor return null; } return $object->getName(); + case PhabricatorDashboardPanelTransaction::TYPE_ARCHIVE: + return (int)$object->getIsArchived(); } return parent::getCustomTransactionOldValue($object, $xaction); @@ -35,6 +38,8 @@ final class PhabricatorDashboardPanelTransactionEditor switch ($xaction->getTransactionType()) { case PhabricatorDashboardPanelTransaction::TYPE_NAME: return $xaction->getNewValue(); + case PhabricatorDashboardPanelTransaction::TYPE_ARCHIVE: + return (int)$xaction->getNewValue(); } return parent::getCustomTransactionNewValue($object, $xaction); } @@ -46,6 +51,9 @@ final class PhabricatorDashboardPanelTransactionEditor case PhabricatorDashboardPanelTransaction::TYPE_NAME: $object->setName($xaction->getNewValue()); return; + case PhabricatorDashboardPanelTransaction::TYPE_ARCHIVE: + $object->setIsArchived((int)$xaction->getNewValue()); + return; case PhabricatorTransactions::TYPE_VIEW_POLICY: $object->setViewPolicy($xaction->getNewValue()); return; @@ -63,6 +71,7 @@ final class PhabricatorDashboardPanelTransactionEditor switch ($xaction->getTransactionType()) { case PhabricatorDashboardPanelTransaction::TYPE_NAME: + case PhabricatorDashboardPanelTransaction::TYPE_ARCHIVE: case PhabricatorTransactions::TYPE_VIEW_POLICY: case PhabricatorTransactions::TYPE_EDIT_POLICY: return; diff --git a/src/applications/dashboard/phid/PhabricatorDashboardPHIDTypePanel.php b/src/applications/dashboard/phid/PhabricatorDashboardPHIDTypePanel.php index 8b075e2602..882f728c1e 100644 --- a/src/applications/dashboard/phid/PhabricatorDashboardPHIDTypePanel.php +++ b/src/applications/dashboard/phid/PhabricatorDashboardPHIDTypePanel.php @@ -38,6 +38,10 @@ final class PhabricatorDashboardPHIDTypePanel extends PhabricatorPHIDType { $handle->setName($panel->getMonogram()); $handle->setFullName("{$monogram} {$name}"); $handle->setURI("/{$monogram}"); + + if ($panel->getIsArchived()) { + $handle->setStatus(PhabricatorObjectHandleStatus::STATUS_CLOSED); + } } } diff --git a/src/applications/dashboard/query/PhabricatorDashboardPanelQuery.php b/src/applications/dashboard/query/PhabricatorDashboardPanelQuery.php index 8e13ee9d5f..7ba1a43ea4 100644 --- a/src/applications/dashboard/query/PhabricatorDashboardPanelQuery.php +++ b/src/applications/dashboard/query/PhabricatorDashboardPanelQuery.php @@ -5,6 +5,7 @@ final class PhabricatorDashboardPanelQuery private $ids; private $phids; + private $archived; public function withIDs(array $ids) { $this->ids = $ids; @@ -16,6 +17,11 @@ final class PhabricatorDashboardPanelQuery return $this; } + public function withArchived($archived) { + $this->archived = $archived; + return $this; + } + protected function loadPage() { $table = new PhabricatorDashboardPanel(); $conn_r = $table->establishConnection('r'); @@ -34,20 +40,27 @@ final class PhabricatorDashboardPanelQuery protected function buildWhereClause($conn_r) { $where = array(); - if ($this->ids) { + if ($this->ids !== null) { $where[] = qsprintf( $conn_r, 'id IN (%Ld)', $this->ids); } - if ($this->phids) { + if ($this->phids !== null) { $where[] = qsprintf( $conn_r, 'phid IN (%Ls)', $this->phids); } + if ($this->archived !== null) { + $where[] = qsprintf( + $conn_r, + 'isArchived = %d', + (int)$this->archived); + } + $where[] = $this->buildPagingClause($conn_r); return $this->formatWhereClause($where); diff --git a/src/applications/dashboard/query/PhabricatorDashboardPanelSearchEngine.php b/src/applications/dashboard/query/PhabricatorDashboardPanelSearchEngine.php index 261a2b3d45..c36425729c 100644 --- a/src/applications/dashboard/query/PhabricatorDashboardPanelSearchEngine.php +++ b/src/applications/dashboard/query/PhabricatorDashboardPanelSearchEngine.php @@ -14,19 +14,47 @@ final class PhabricatorDashboardPanelSearchEngine public function buildSavedQueryFromRequest(AphrontRequest $request) { $saved = new PhabricatorSavedQuery(); + $saved->setParameter('status', $request->getStr('status')); + return $saved; } public function buildQueryFromSavedQuery(PhabricatorSavedQuery $saved) { $query = id(new PhabricatorDashboardPanelQuery()); + $status = $saved->getParameter('status'); + switch ($status) { + case 'active': + $query->withArchived(false); + break; + case 'archived': + $query->withArchived(true); + break; + default: + break; + } + return $query; } public function buildSearchForm( AphrontFormView $form, PhabricatorSavedQuery $saved_query) { - return; + + $status = $saved_query->getParameter('status', ''); + + $form + ->appendChild( + id(new AphrontFormSelectControl()) + ->setLabel(pht('Status')) + ->setName('status') + ->setValue($status) + ->setOptions( + array( + '' => pht('(All Panels)'), + 'active' => pht('Active Panels'), + 'archived' => pht('Archived Panels'), + ))); } protected function getURI($path) { @@ -35,6 +63,7 @@ final class PhabricatorDashboardPanelSearchEngine public function getBuiltinQueryNames() { $names = array( + 'active' => pht('Active Panels'), 'all' => pht('All Panels'), ); @@ -47,6 +76,8 @@ final class PhabricatorDashboardPanelSearchEngine $query->setQueryKey($query_key); switch ($query_key) { + case 'active': + return $query->setParameter('status', 'active'); case 'all': return $query; } @@ -70,6 +101,21 @@ final class PhabricatorDashboardPanelSearchEngine ->setHref('/'.$panel->getMonogram()) ->setObject($panel); + $impl = $panel->getImplementation(); + if ($impl) { + $type_text = $impl->getPanelTypeName(); + $type_icon = 'none'; + } else { + $type_text = nonempty($panel->getPanelType(), pht('Unknown Type')); + $type_icon = 'fa-question'; + } + + $item->addIcon($type_icon, $type_text); + + if ($panel->getIsArchived()) { + $item->setDisabled(true); + } + $list->addItem($item); } diff --git a/src/applications/dashboard/storage/PhabricatorDashboardPanel.php b/src/applications/dashboard/storage/PhabricatorDashboardPanel.php index b5625117e9..158a637d2d 100644 --- a/src/applications/dashboard/storage/PhabricatorDashboardPanel.php +++ b/src/applications/dashboard/storage/PhabricatorDashboardPanel.php @@ -13,6 +13,7 @@ final class PhabricatorDashboardPanel protected $panelType; protected $viewPolicy; protected $editPolicy; + protected $isArchived = 0; protected $properties = array(); private $customFields = self::ATTACHABLE; diff --git a/src/applications/dashboard/storage/PhabricatorDashboardPanelTransaction.php b/src/applications/dashboard/storage/PhabricatorDashboardPanelTransaction.php index 7169081e0d..9e0bcd338c 100644 --- a/src/applications/dashboard/storage/PhabricatorDashboardPanelTransaction.php +++ b/src/applications/dashboard/storage/PhabricatorDashboardPanelTransaction.php @@ -4,6 +4,7 @@ final class PhabricatorDashboardPanelTransaction extends PhabricatorApplicationTransaction { const TYPE_NAME = 'dashpanel:name'; + const TYPE_ARCHIVE = 'dashboard:archive'; public function getApplicationName() { return 'dashboard'; @@ -36,6 +37,16 @@ final class PhabricatorDashboardPanelTransaction $old, $new); } + case self::TYPE_ARCHIVE: + if ($new) { + return pht( + '%s archived this panel.', + $author_link); + } else { + return pht( + '%s activated this panel.', + $author_link); + } } return parent::getTitle(); @@ -67,6 +78,18 @@ final class PhabricatorDashboardPanelTransaction $old, $new); } + case self::TYPE_ARCHIVE: + if ($new) { + return pht( + '%s archived dashboard panel %s.', + $author_link, + $object_link); + } else { + return pht( + '%s activated dashboard panel %s.', + $author_link, + $object_link); + } } return parent::getTitleForFeed($story);