diff --git a/resources/celerity/map.php b/resources/celerity/map.php index e50636d3bb..0115b0ce9a 100644 --- a/resources/celerity/map.php +++ b/resources/celerity/map.php @@ -7,7 +7,7 @@ */ return array( 'names' => array( - 'core.pkg.css' => 'ea0dfb3d', + 'core.pkg.css' => '9968bf8d', 'core.pkg.js' => '6972d365', 'darkconsole.pkg.js' => 'e7393ebb', 'differential.pkg.css' => '7ba78475', @@ -113,7 +113,7 @@ return array( 'rsrc/css/font/font-lato.css' => 'c7ccd872', 'rsrc/css/font/phui-font-icon-base.css' => '6449bce8', 'rsrc/css/layout/phabricator-filetree-view.css' => 'fccf9f82', - 'rsrc/css/layout/phabricator-side-menu-view.css' => '3a3d9f41', + 'rsrc/css/layout/phabricator-side-menu-view.css' => 'dd849797', 'rsrc/css/layout/phabricator-source-code-view.css' => 'cbeef983', 'rsrc/css/phui/calendar/phui-calendar-day.css' => 'd1cf6f93', 'rsrc/css/phui/calendar/phui-calendar-list.css' => 'c1c7f338', @@ -780,7 +780,7 @@ return array( 'phabricator-remarkup-css' => '6aae5360', 'phabricator-search-results-css' => '7dea472c', 'phabricator-shaped-request' => '7cbe244b', - 'phabricator-side-menu-view-css' => '3a3d9f41', + 'phabricator-side-menu-view-css' => 'dd849797', 'phabricator-slowvote-css' => 'a94b7230', 'phabricator-source-code-view-css' => 'cbeef983', 'phabricator-standard-page-view' => 'e709f6d0', diff --git a/src/applications/diffusion/controller/DiffusionRepositoryManageController.php b/src/applications/diffusion/controller/DiffusionRepositoryManageController.php index aa34f8f909..4f4624b70d 100644 --- a/src/applications/diffusion/controller/DiffusionRepositoryManageController.php +++ b/src/applications/diffusion/controller/DiffusionRepositoryManageController.php @@ -106,9 +106,19 @@ final class DiffusionRepositoryManageController ->setBaseURI($base_uri); foreach ($panels as $panel) { - $nav->addFilter( - $panel->getManagementPanelKey(), - $panel->getManagementPanelLabel()); + $key = $panel->getManagementPanelKey(); + $label = $panel->getManagementPanelLabel(); + $icon = $panel->getManagementPanelIcon(); + $href = $repository->getPathURI("manage/{$key}/"); + + $item = id(new PHUIListItemView()) + ->setKey($key) + ->setName($label) + ->setType(PHUIListItemView::TYPE_LINK) + ->setHref($href) + ->setIcon($icon); + + $nav->addMenuItem($item); } $nav->selectFilter($selected); diff --git a/src/applications/diffusion/management/DiffusionRepositoryActionsManagementPanel.php b/src/applications/diffusion/management/DiffusionRepositoryActionsManagementPanel.php index 14bcc250d9..3a82879b26 100644 --- a/src/applications/diffusion/management/DiffusionRepositoryActionsManagementPanel.php +++ b/src/applications/diffusion/management/DiffusionRepositoryActionsManagementPanel.php @@ -13,6 +13,23 @@ final class DiffusionRepositoryActionsManagementPanel return 1100; } + public function getManagementPanelIcon() { + $repository = $this->getRepository(); + + $has_any = + $repository->getDetail('herald-disabled') || + $repository->getDetail('disable-autoclose'); + + // NOTE: Any value here really means something is disabled, so try to + // hint that a little bit with the icon. + + if ($has_any) { + return 'fa-comment-o'; + } else { + return 'fa-commenting grey'; + } + } + protected function getEditEngineFieldKeys() { return array( 'publish', diff --git a/src/applications/diffusion/management/DiffusionRepositoryAutomationManagementPanel.php b/src/applications/diffusion/management/DiffusionRepositoryAutomationManagementPanel.php index 911a594d05..764f58c5bd 100644 --- a/src/applications/diffusion/management/DiffusionRepositoryAutomationManagementPanel.php +++ b/src/applications/diffusion/management/DiffusionRepositoryAutomationManagementPanel.php @@ -19,6 +19,28 @@ final class DiffusionRepositoryAutomationManagementPanel ); } + public function getManagementPanelIcon() { + $repository = $this->getRepository(); + + if (!$repository->canPerformAutomation()) { + return 'fa-truck grey'; + } + + $blueprint_phids = $repository->getAutomationBlueprintPHIDs(); + if (!$blueprint_phids) { + return 'fa-truck grey'; + } + + $is_authorized = DrydockAuthorizationQuery::isFullyAuthorized( + $repository->getPHID(), + $blueprint_phids); + if (!$is_authorized) { + return 'fa-exclamation-triangle yellow'; + } + + return 'fa-truck'; + } + protected function buildManagementPanelActions() { $repository = $this->getRepository(); $viewer = $this->getViewer(); diff --git a/src/applications/diffusion/management/DiffusionRepositoryBasicsManagementPanel.php b/src/applications/diffusion/management/DiffusionRepositoryBasicsManagementPanel.php index 40ba95045a..96bda40246 100644 --- a/src/applications/diffusion/management/DiffusionRepositoryBasicsManagementPanel.php +++ b/src/applications/diffusion/management/DiffusionRepositoryBasicsManagementPanel.php @@ -13,6 +13,16 @@ final class DiffusionRepositoryBasicsManagementPanel return 100; } + public function getManagementPanelIcon() { + $repository = $this->getRepository(); + + if (!$repository->isTracked()) { + return 'fa-ban indigo'; + } else { + return 'fa-code'; + } + } + protected function getEditEngineFieldKeys() { return array( 'name', diff --git a/src/applications/diffusion/management/DiffusionRepositoryBranchesManagementPanel.php b/src/applications/diffusion/management/DiffusionRepositoryBranchesManagementPanel.php index 4ba7eed73c..66ac0877dd 100644 --- a/src/applications/diffusion/management/DiffusionRepositoryBranchesManagementPanel.php +++ b/src/applications/diffusion/management/DiffusionRepositoryBranchesManagementPanel.php @@ -13,6 +13,21 @@ final class DiffusionRepositoryBranchesManagementPanel return 1000; } + public function getManagementPanelIcon() { + $repository = $this->getRepository(); + + $has_any = + $repository->getDetail('default-branch') || + $repository->getDetail('branch-filter') || + $repository->getDetail('close-commits-filter'); + + if ($has_any) { + return 'fa-code-fork'; + } else { + return 'fa-code-fork grey'; + } + } + protected function getEditEngineFieldKeys() { return array( 'defaultBranch', diff --git a/src/applications/diffusion/management/DiffusionRepositoryHistoryManagementPanel.php b/src/applications/diffusion/management/DiffusionRepositoryHistoryManagementPanel.php index e574030bfc..c1a812dca0 100644 --- a/src/applications/diffusion/management/DiffusionRepositoryHistoryManagementPanel.php +++ b/src/applications/diffusion/management/DiffusionRepositoryHistoryManagementPanel.php @@ -13,6 +13,10 @@ final class DiffusionRepositoryHistoryManagementPanel return 2000; } + public function getManagementPanelIcon() { + return 'fa-list-ul'; + } + public function buildManagementPanelContent() { return $this->newTimeline(); } diff --git a/src/applications/diffusion/management/DiffusionRepositoryManagementPanel.php b/src/applications/diffusion/management/DiffusionRepositoryManagementPanel.php index a8f68d71b9..efb165d801 100644 --- a/src/applications/diffusion/management/DiffusionRepositoryManagementPanel.php +++ b/src/applications/diffusion/management/DiffusionRepositoryManagementPanel.php @@ -38,6 +38,10 @@ abstract class DiffusionRepositoryManagementPanel abstract public function getManagementPanelOrder(); abstract public function buildManagementPanelContent(); + public function getManagementPanelIcon() { + return 'fa-pencil'; + } + protected function buildManagementPanelActions() { return array(); } diff --git a/src/applications/diffusion/management/DiffusionRepositoryPoliciesManagementPanel.php b/src/applications/diffusion/management/DiffusionRepositoryPoliciesManagementPanel.php index 7cca25d95c..da53970fee 100644 --- a/src/applications/diffusion/management/DiffusionRepositoryPoliciesManagementPanel.php +++ b/src/applications/diffusion/management/DiffusionRepositoryPoliciesManagementPanel.php @@ -13,6 +13,38 @@ final class DiffusionRepositoryPoliciesManagementPanel return 300; } + public function getManagementPanelIcon() { + $viewer = $this->getViewer(); + $repository = $this->getRepository(); + + $can_view = PhabricatorPolicyCapability::CAN_VIEW; + $can_edit = PhabricatorPolicyCapability::CAN_EDIT; + $can_push = DiffusionPushCapability::CAPABILITY; + + $actual_values = array( + 'spacePHID' => $repository->getSpacePHID(), + 'view' => $repository->getPolicy($can_view), + 'edit' => $repository->getPolicy($can_edit), + 'push' => $repository->getPolicy($can_push), + ); + + $default = PhabricatorRepository::initializeNewRepository( + $viewer); + + $default_values = array( + 'spacePHID' => $default->getSpacePHID(), + 'view' => $default->getPolicy($can_view), + 'edit' => $default->getPolicy($can_edit), + 'push' => $default->getPolicy($can_push), + ); + + if ($actual_values === $default_values) { + return 'fa-lock grey'; + } else { + return 'fa-lock'; + } + } + protected function getEditEngineFieldKeys() { return array( 'policy.view', diff --git a/src/applications/diffusion/management/DiffusionRepositoryStagingManagementPanel.php b/src/applications/diffusion/management/DiffusionRepositoryStagingManagementPanel.php index 09cc3c58c4..0d8f9379be 100644 --- a/src/applications/diffusion/management/DiffusionRepositoryStagingManagementPanel.php +++ b/src/applications/diffusion/management/DiffusionRepositoryStagingManagementPanel.php @@ -13,6 +13,18 @@ final class DiffusionRepositoryStagingManagementPanel return 700; } + public function getManagementPanelIcon() { + $repository = $this->getRepository(); + + $staging_uri = $repository->getStagingURI(); + + if ($staging_uri) { + return 'fa-upload'; + } else { + return 'fa-upload grey'; + } + } + protected function getEditEngineFieldKeys() { return array( 'stagingAreaURI', diff --git a/src/applications/diffusion/management/DiffusionRepositoryStatusManagementPanel.php b/src/applications/diffusion/management/DiffusionRepositoryStatusManagementPanel.php index 1666749980..eba7722f2f 100644 --- a/src/applications/diffusion/management/DiffusionRepositoryStatusManagementPanel.php +++ b/src/applications/diffusion/management/DiffusionRepositoryStatusManagementPanel.php @@ -13,6 +13,21 @@ final class DiffusionRepositoryStatusManagementPanel return 200; } + public function getManagementPanelIcon() { + $repository = $this->getRepository(); + + // TODO: We could try to show a warning icon in more cases, but just + // raise in the most serious cases for now. + $messages = $this->loadStatusMessages($repository); + + $raw_error = $this->buildRepositoryRawError($repository, $messages); + if ($raw_error) { + return 'fa-exclamation-triangle red'; + } + + return 'fa-check grey'; + } + protected function buildManagementPanelActions() { $repository = $this->getRepository(); $viewer = $this->getViewer(); @@ -46,9 +61,7 @@ final class DiffusionRepositoryStatusManagementPanel pht('Update Frequency'), $this->buildRepositoryUpdateInterval($repository)); - $messages = id(new PhabricatorRepositoryStatusMessage()) - ->loadAllWhere('repositoryID = %d', $repository->getID()); - $messages = mpull($messages, null, 'getStatusType'); + $messages = $this->loadStatusMessages($repository); $status = $this->buildRepositoryStatus($repository, $messages); $raw_error = $this->buildRepositoryRawError($repository, $messages); @@ -469,5 +482,13 @@ final class DiffusionRepositoryStatusManagementPanel return $raw_message; } + private function loadStatusMessages(PhabricatorRepository $repository) { + $messages = id(new PhabricatorRepositoryStatusMessage()) + ->loadAllWhere('repositoryID = %d', $repository->getID()); + $messages = mpull($messages, null, 'getStatusType'); + + return $messages; + } + } diff --git a/src/applications/diffusion/management/DiffusionRepositoryStorageManagementPanel.php b/src/applications/diffusion/management/DiffusionRepositoryStorageManagementPanel.php index 54c446b9fe..734b4c6f8e 100644 --- a/src/applications/diffusion/management/DiffusionRepositoryStorageManagementPanel.php +++ b/src/applications/diffusion/management/DiffusionRepositoryStorageManagementPanel.php @@ -13,6 +13,18 @@ final class DiffusionRepositoryStorageManagementPanel return 600; } + public function getManagementPanelIcon() { + $repository = $this->getRepository(); + + if ($repository->getAlmanacServicePHID()) { + return 'fa-sitemap'; + } else if ($repository->isHosted()) { + return 'fa-folder'; + } else { + return 'fa-download'; + } + } + public function buildManagementPanelContent() { return array( $this->buildStorageStatusPanel(), diff --git a/src/applications/diffusion/management/DiffusionRepositorySymbolsManagementPanel.php b/src/applications/diffusion/management/DiffusionRepositorySymbolsManagementPanel.php index 3a9d94a54d..996473f4f1 100644 --- a/src/applications/diffusion/management/DiffusionRepositorySymbolsManagementPanel.php +++ b/src/applications/diffusion/management/DiffusionRepositorySymbolsManagementPanel.php @@ -13,6 +13,20 @@ final class DiffusionRepositorySymbolsManagementPanel return 900; } + public function getManagementPanelIcon() { + $repository = $this->getRepository(); + + $has_any = + $repository->getSymbolLanguages() || + $repository->getSymbolSources(); + + if ($has_any) { + return 'fa-link'; + } else { + return 'fa-link grey'; + } + } + protected function getEditEngineFieldKeys() { return array( 'symbolLanguages', diff --git a/src/applications/diffusion/management/DiffusionRepositoryURIsManagementPanel.php b/src/applications/diffusion/management/DiffusionRepositoryURIsManagementPanel.php index 634535fef4..45047dd4fe 100644 --- a/src/applications/diffusion/management/DiffusionRepositoryURIsManagementPanel.php +++ b/src/applications/diffusion/management/DiffusionRepositoryURIsManagementPanel.php @@ -9,8 +9,12 @@ final class DiffusionRepositoryURIsManagementPanel return pht('Clone / Fetch / Mirror'); } + public function getManagementPanelIcon() { + return 'fa-cogs'; + } + public function getManagementPanelOrder() { - return 300; + return 400; } public function buildManagementPanelContent() { diff --git a/src/applications/drydock/query/DrydockAuthorizationQuery.php b/src/applications/drydock/query/DrydockAuthorizationQuery.php index 6d2cddcf8a..d6436fc93a 100644 --- a/src/applications/drydock/query/DrydockAuthorizationQuery.php +++ b/src/applications/drydock/query/DrydockAuthorizationQuery.php @@ -9,6 +9,35 @@ final class DrydockAuthorizationQuery extends DrydockQuery { private $blueprintStates; private $objectStates; + public static function isFullyAuthorized( + $object_phid, + array $blueprint_phids) { + + if (!$blueprint_phids) { + return true; + } + + $authorizations = id(new self()) + ->setViewer(PhabricatorUser::getOmnipotentUser()) + ->withObjectPHIDs(array($object_phid)) + ->withBlueprintPHIDs($blueprint_phids) + ->execute(); + $authorizations = mpull($authorizations, null, 'getBlueprintPHID'); + + foreach ($blueprint_phids as $phid) { + $authorization = idx($authorizations, $phid); + if (!$authorization) { + return false; + } + + if (!$authorization->isAuthorized()) { + return false; + } + } + + return true; + } + public function withIDs(array $ids) { $this->ids = $ids; return $this; diff --git a/src/applications/drydock/storage/DrydockAuthorization.php b/src/applications/drydock/storage/DrydockAuthorization.php index ea1160b23b..9503a03767 100644 --- a/src/applications/drydock/storage/DrydockAuthorization.php +++ b/src/applications/drydock/storage/DrydockAuthorization.php @@ -93,6 +93,11 @@ final class DrydockAuthorization extends DrydockDAO return idx($map, $state, pht('', $state)); } + public function isAuthorized() { + $state = $this->getBlueprintAuthorizationState(); + return ($state == self::BLUEPRINTAUTH_AUTHORIZED); + } + /** * Apply external authorization effects after a user chagnes the value of a * blueprint selector control an object. diff --git a/webroot/rsrc/css/layout/phabricator-side-menu-view.css b/webroot/rsrc/css/layout/phabricator-side-menu-view.css index 77c0b7cf39..b64fe5fbb5 100644 --- a/webroot/rsrc/css/layout/phabricator-side-menu-view.css +++ b/webroot/rsrc/css/layout/phabricator-side-menu-view.css @@ -18,6 +18,12 @@ border-bottom-right-radius: 3px; } +.phabricator-basic-nav .phabricator-side-menu .phui-list-item-icon { + margin-left: -12px; + text-align: center; + width: 24px; +} + .phabricator-basic-nav .phabricator-side-menu .phui-list-item-selected { background-color: rgba({$alphablack},.05); border-left: 4px solid {$sky};