@recaptime-dev's working patches + fork for Phorge, a community fork of Phabricator. (Upstream dev and stable branches are at upstream/main and upstream/stable respectively.) hq.recaptime.dev/wiki/Phorge
phorge phabricator
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

Update Repository Management pages to new fixed UI

Summary: Simplifies the Repository Management pages to the new fixed column layout. I've also moved "Status" into the Basics page, which feels better, and moved "Documentation" as a nav item to a button in the header. This removed "action list" and "curtain view" from the management panels and uses the new bits from Config/Phacility. Undecided if the icons should stay or go for the nav. Left them in for Diffusion. I want to update the EditEngine pages to display in this UI and not leave the portal, but I haven't dug into that this page. I'm a bit worried it will not easily be possible.

Test Plan:
Generate a svn, git, hg repository, test each of the new pages and each of the new buttons. Activate, deactivate, etc.

{F5164674}

Reviewers: epriestley

Reviewed By: epriestley

Spies: Korvin

Differential Revision: https://secure.phabricator.com/D18523

+749 -978
+5 -5
resources/celerity/map.php
··· 9 9 'names' => array( 10 10 'conpherence.pkg.css' => 'e68cf1fa', 11 11 'conpherence.pkg.js' => 'b5b51108', 12 - 'core.pkg.css' => '042e1782', 12 + 'core.pkg.css' => 'ebbf04f7', 13 13 'core.pkg.js' => '6c085267', 14 14 'darkconsole.pkg.js' => '1f9a31bc', 15 15 'differential.pkg.css' => '45951e9e', ··· 142 142 'rsrc/css/phui/phui-badge.css' => '22c0cf4f', 143 143 'rsrc/css/phui/phui-basic-nav-view.css' => '98c11ab3', 144 144 'rsrc/css/phui/phui-big-info-view.css' => 'acc3492c', 145 - 'rsrc/css/phui/phui-box.css' => '4165eb0d', 145 + 'rsrc/css/phui/phui-box.css' => '9f3745fb', 146 146 'rsrc/css/phui/phui-chart.css' => '6bf6f78e', 147 147 'rsrc/css/phui/phui-cms.css' => '504b4b23', 148 148 'rsrc/css/phui/phui-comment-form.css' => 'ac68149f', ··· 157 157 'rsrc/css/phui/phui-form-view.css' => 'ae9f8d16', 158 158 'rsrc/css/phui/phui-form.css' => '7aaa04e3', 159 159 'rsrc/css/phui/phui-head-thing.css' => 'fd311e5f', 160 - 'rsrc/css/phui/phui-header-view.css' => '3c722648', 160 + 'rsrc/css/phui/phui-header-view.css' => '369275d6', 161 161 'rsrc/css/phui/phui-hovercard.css' => 'f0592bcf', 162 162 'rsrc/css/phui/phui-icon-set-selector.css' => '87db8fee', 163 163 'rsrc/css/phui/phui-icon.css' => '5c4a5de6', ··· 820 820 'phui-badge-view-css' => '22c0cf4f', 821 821 'phui-basic-nav-view-css' => '98c11ab3', 822 822 'phui-big-info-view-css' => 'acc3492c', 823 - 'phui-box-css' => '4165eb0d', 823 + 'phui-box-css' => '9f3745fb', 824 824 'phui-button-bar-css' => 'f1ff5494', 825 825 'phui-button-css' => '1863cc6e', 826 826 'phui-button-simple-css' => '8e1baf68', ··· 843 843 'phui-form-css' => '7aaa04e3', 844 844 'phui-form-view-css' => 'ae9f8d16', 845 845 'phui-head-thing-view-css' => 'fd311e5f', 846 - 'phui-header-view-css' => '3c722648', 846 + 'phui-header-view-css' => '369275d6', 847 847 'phui-hovercard' => '1bd28176', 848 848 'phui-hovercard-view-css' => 'f0592bcf', 849 849 'phui-icon-set-selector-css' => '87db8fee',
-4
src/__phutil_library_map__.php
··· 843 843 'DiffusionRepositoryController' => 'applications/diffusion/controller/DiffusionRepositoryController.php', 844 844 'DiffusionRepositoryDatasource' => 'applications/diffusion/typeahead/DiffusionRepositoryDatasource.php', 845 845 'DiffusionRepositoryDefaultController' => 'applications/diffusion/controller/DiffusionRepositoryDefaultController.php', 846 - 'DiffusionRepositoryDocumentationManagementPanel' => 'applications/diffusion/management/DiffusionRepositoryDocumentationManagementPanel.php', 847 846 'DiffusionRepositoryEditActivateController' => 'applications/diffusion/controller/DiffusionRepositoryEditActivateController.php', 848 847 'DiffusionRepositoryEditConduitAPIMethod' => 'applications/diffusion/conduit/DiffusionRepositoryEditConduitAPIMethod.php', 849 848 'DiffusionRepositoryEditController' => 'applications/diffusion/controller/DiffusionRepositoryEditController.php', ··· 864 863 'DiffusionRepositoryRemarkupRule' => 'applications/diffusion/remarkup/DiffusionRepositoryRemarkupRule.php', 865 864 'DiffusionRepositorySearchConduitAPIMethod' => 'applications/diffusion/conduit/DiffusionRepositorySearchConduitAPIMethod.php', 866 865 'DiffusionRepositoryStagingManagementPanel' => 'applications/diffusion/management/DiffusionRepositoryStagingManagementPanel.php', 867 - 'DiffusionRepositoryStatusManagementPanel' => 'applications/diffusion/management/DiffusionRepositoryStatusManagementPanel.php', 868 866 'DiffusionRepositoryStorageManagementPanel' => 'applications/diffusion/management/DiffusionRepositoryStorageManagementPanel.php', 869 867 'DiffusionRepositorySubversionManagementPanel' => 'applications/diffusion/management/DiffusionRepositorySubversionManagementPanel.php', 870 868 'DiffusionRepositorySymbolsManagementPanel' => 'applications/diffusion/management/DiffusionRepositorySymbolsManagementPanel.php', ··· 5863 5861 'DiffusionRepositoryController' => 'DiffusionController', 5864 5862 'DiffusionRepositoryDatasource' => 'PhabricatorTypeaheadDatasource', 5865 5863 'DiffusionRepositoryDefaultController' => 'DiffusionController', 5866 - 'DiffusionRepositoryDocumentationManagementPanel' => 'DiffusionRepositoryManagementPanel', 5867 5864 'DiffusionRepositoryEditActivateController' => 'DiffusionRepositoryManageController', 5868 5865 'DiffusionRepositoryEditConduitAPIMethod' => 'PhabricatorEditEngineAPIMethod', 5869 5866 'DiffusionRepositoryEditController' => 'DiffusionRepositoryManageController', ··· 5884 5881 'DiffusionRepositoryRemarkupRule' => 'PhabricatorObjectRemarkupRule', 5885 5882 'DiffusionRepositorySearchConduitAPIMethod' => 'PhabricatorSearchEngineAPIMethod', 5886 5883 'DiffusionRepositoryStagingManagementPanel' => 'DiffusionRepositoryManagementPanel', 5887 - 'DiffusionRepositoryStatusManagementPanel' => 'DiffusionRepositoryManagementPanel', 5888 5884 'DiffusionRepositoryStorageManagementPanel' => 'DiffusionRepositoryManagementPanel', 5889 5885 'DiffusionRepositorySubversionManagementPanel' => 'DiffusionRepositoryManagementPanel', 5890 5886 'DiffusionRepositorySymbolsManagementPanel' => 'DiffusionRepositoryManagementPanel',
+1 -1
src/applications/diffusion/controller/DiffusionRepositoryEditUpdateController.php
··· 13 13 $drequest = $this->getDiffusionRequest(); 14 14 $repository = $drequest->getRepository(); 15 15 16 - $panel_uri = id(new DiffusionRepositoryStatusManagementPanel()) 16 + $panel_uri = id(new DiffusionRepositoryBasicsManagementPanel()) 17 17 ->setRepository($repository) 18 18 ->getPanelURI(); 19 19
+16
src/applications/diffusion/controller/DiffusionRepositoryManageController.php
··· 22 22 return $crumbs; 23 23 } 24 24 25 + public function newBox($title, $content, $action = null) { 26 + $header = id(new PHUIHeaderView()) 27 + ->setHeader($title); 28 + 29 + if ($action) { 30 + $header->addActionItem($action); 31 + } 32 + 33 + $view = id(new PHUIObjectBoxView()) 34 + ->setHeader($header) 35 + ->appendChild($content) 36 + ->setBackground(PHUIObjectBoxView::WHITE_CONFIG); 37 + 38 + return $view; 39 + } 40 + 25 41 }
+47 -37
src/applications/diffusion/controller/DiffusionRepositoryManagePanelsController.php
··· 53 53 54 54 $panel = $panels[$selected]; 55 55 56 + $crumbs = $this->buildApplicationCrumbs(); 57 + $crumbs->addTextCrumb($panel->getManagementPanelLabel()); 58 + $crumbs->setBorder(true); 59 + 56 60 $content = $panel->buildManagementPanelContent(); 57 61 58 62 $title = array( ··· 60 64 $repository->getDisplayName(), 61 65 ); 62 66 63 - $crumbs = $this->buildApplicationCrumbs(); 64 - $crumbs->addTextCrumb($panel->getManagementPanelLabel()); 65 - $crumbs->setBorder(true); 66 - 67 - $header_text = pht( 68 - '%s: %s', 69 - $repository->getDisplayName(), 70 - $panel->getManagementPanelLabel()); 71 - 72 - $header = id(new PHUIHeaderView()) 73 - ->setHeader($header_text) 74 - ->setHeaderIcon('fa-pencil'); 75 - if ($repository->isTracked()) { 76 - $header->setStatus('fa-check', 'bluegrey', pht('Active')); 77 - } else { 78 - $header->setStatus('fa-ban', 'dark', pht('Inactive')); 79 - } 80 - 81 - $header->addActionLink( 82 - id(new PHUIButtonView()) 83 - ->setTag('a') 84 - ->setText(pht('View Repository')) 85 - ->setHref($repository->getURI()) 86 - ->setIcon('fa-code') 87 - ->setColor(PHUIButtonView::GREEN)); 67 + $header = $this->buildHeaderView($repository->getDisplayName()); 88 68 89 69 $view = id(new PHUITwoColumnView()) 90 70 ->setHeader($header) 71 + ->setNavigation($nav) 72 + ->setFixed(true) 91 73 ->setMainColumn($content); 92 74 93 - $curtain = $panel->buildManagementPanelCurtain(); 94 - if ($curtain) { 95 - $view->setCurtain($curtain); 96 - } 97 - 98 75 return $this->newPage() 99 76 ->setTitle($title) 100 77 ->setCrumbs($crumbs) 101 - ->setNavigation($nav) 102 78 ->appendChild($view); 103 79 } 104 80 ··· 113 89 $nav = id(new AphrontSideNavFilterView()) 114 90 ->setBaseURI($base_uri); 115 91 116 - $item = id(new PHUIListItemView()) 117 - ->setName(pht('manage')) 118 - ->setType(PHUIListItemView::TYPE_LABEL); 119 - 120 - $nav->addMenuItem($item); 121 - 122 92 foreach ($panels as $panel) { 123 93 $key = $panel->getManagementPanelKey(); 124 94 $label = $panel->getManagementPanelLabel(); ··· 138 108 $nav->selectFilter($selected); 139 109 140 110 return $nav; 111 + } 112 + 113 + public function buildHeaderView($title) { 114 + $viewer = $this->getViewer(); 115 + 116 + $drequest = $this->getDiffusionRequest(); 117 + $repository = $drequest->getRepository(); 118 + 119 + $header = id(new PHUIHeaderView()) 120 + ->setHeader($title) 121 + ->setProfileHeader(true) 122 + ->setHref($repository->getURI()) 123 + ->setImage($repository->getProfileImageURI()); 124 + 125 + if ($repository->isTracked()) { 126 + $header->setStatus('fa-check', 'bluegrey', pht('Active')); 127 + } else { 128 + $header->setStatus('fa-ban', 'dark', pht('Inactive')); 129 + } 130 + 131 + $doc_href = PhabricatorEnv::getDoclink( 132 + 'Diffusion User Guide: Managing Repositories'); 133 + 134 + $header->addActionLink( 135 + id(new PHUIButtonView()) 136 + ->setTag('a') 137 + ->setText(pht('View Repository')) 138 + ->setHref($repository->getURI()) 139 + ->setIcon('fa-code') 140 + ->setColor(PHUIButtonView::GREY)); 141 + 142 + $header->addActionLink( 143 + id(new PHUIButtonView()) 144 + ->setTag('a') 145 + ->setIcon('fa-book') 146 + ->setHref($doc_href) 147 + ->setText(pht('Help')) 148 + ->setColor(PHUIButtonView::GREY)); 149 + 150 + return $header; 141 151 } 142 152 143 153 public function newTimeline(PhabricatorRepository $repository) {
+17 -38
src/applications/diffusion/management/DiffusionRepositoryActionsManagementPanel.php
··· 14 14 } 15 15 16 16 public function getManagementPanelIcon() { 17 - $repository = $this->getRepository(); 18 - 19 - $has_any = 20 - $repository->getDetail('herald-disabled') || 21 - $repository->getDetail('disable-autoclose'); 22 - 23 - // NOTE: Any value here really means something is disabled, so try to 24 - // hint that a little bit with the icon. 25 - 26 - if ($has_any) { 27 - return 'fa-comment-o'; 28 - } else { 29 - return 'fa-commenting grey'; 30 - } 17 + return 'fa-flash'; 31 18 } 32 19 33 20 protected function getEditEngineFieldKeys() { ··· 37 24 ); 38 25 } 39 26 40 - public function buildManagementPanelCurtain() { 41 - $repository = $this->getRepository(); 42 - $viewer = $this->getViewer(); 43 - $action_list = $this->getNewActionList(); 44 - 45 - $can_edit = PhabricatorPolicyFilter::hasCapability( 46 - $viewer, 47 - $repository, 48 - PhabricatorPolicyCapability::CAN_EDIT); 49 - 50 - $actions_uri = $this->getEditPageURI(); 51 - 52 - $action_list->addAction( 53 - id(new PhabricatorActionView()) 54 - ->setIcon('fa-pencil') 55 - ->setName(pht('Edit Actions')) 56 - ->setHref($actions_uri) 57 - ->setDisabled(!$can_edit) 58 - ->setWorkflow(!$can_edit)); 59 - 60 - return $this->getNewCurtainView($action_list); 61 - } 62 - 63 27 public function buildManagementPanelContent() { 64 28 $repository = $this->getRepository(); 65 29 $viewer = $this->getViewer(); ··· 79 43 $autoclose = phutil_tag('em', array(), $autoclose); 80 44 $view->addProperty(pht('Autoclose'), $autoclose); 81 45 82 - return $this->newBox(pht('Actions'), $view); 46 + $can_edit = PhabricatorPolicyFilter::hasCapability( 47 + $viewer, 48 + $repository, 49 + PhabricatorPolicyCapability::CAN_EDIT); 50 + 51 + $actions_uri = $this->getEditPageURI(); 52 + 53 + $button = id(new PHUIButtonView()) 54 + ->setTag('a') 55 + ->setIcon('fa-pencil') 56 + ->setText(pht('Edit')) 57 + ->setHref($actions_uri) 58 + ->setDisabled(!$can_edit) 59 + ->setWorkflow(!$can_edit); 60 + 61 + return $this->newBox(pht('Actions'), $view, array($button)); 83 62 } 84 63 85 64 }
+28 -43
src/applications/diffusion/management/DiffusionRepositoryAutomationManagementPanel.php
··· 27 27 public function getManagementPanelIcon() { 28 28 $repository = $this->getRepository(); 29 29 30 - if (!$repository->canPerformAutomation()) { 31 - return 'fa-truck grey'; 32 - } 33 - 34 30 $blueprint_phids = $repository->getAutomationBlueprintPHIDs(); 35 - if (!$blueprint_phids) { 36 - return 'fa-truck grey'; 37 - } 38 31 39 32 $is_authorized = DrydockAuthorizationQuery::isFullyAuthorized( 40 33 $repository->getPHID(), 41 34 $blueprint_phids); 42 35 if (!$is_authorized) { 43 - return 'fa-exclamation-triangle yellow'; 36 + return 'fa-exclamation-triangle'; 44 37 } 45 38 46 39 return 'fa-truck'; 47 40 } 48 41 49 - public function buildManagementPanelCurtain() { 50 - $repository = $this->getRepository(); 51 - $viewer = $this->getViewer(); 52 - $action_list = $this->getNewActionList(); 53 - 54 - $can_edit = PhabricatorPolicyFilter::hasCapability( 55 - $viewer, 56 - $repository, 57 - PhabricatorPolicyCapability::CAN_EDIT); 58 - 59 - $can_test = $can_edit && $repository->canPerformAutomation(); 60 - 61 - $automation_uri = $this->getEditPageURI(); 62 - $test_uri = $repository->getPathURI('edit/testautomation/'); 63 - 64 - $action_list->addAction( 65 - id(new PhabricatorActionView()) 66 - ->setIcon('fa-pencil') 67 - ->setName(pht('Edit Automation')) 68 - ->setHref($automation_uri) 69 - ->setDisabled(!$can_edit) 70 - ->setWorkflow(!$can_edit)); 71 - 72 - $action_list->addAction( 73 - id(new PhabricatorActionView()) 74 - ->setIcon('fa-gamepad') 75 - ->setName(pht('Test Configuration')) 76 - ->setWorkflow(true) 77 - ->setDisabled(!$can_test) 78 - ->setHref($test_uri)); 79 - 80 - return $this->getNewCurtainView($action_list); 81 - } 82 - 83 42 public function buildManagementPanelContent() { 84 43 $repository = $this->getRepository(); 85 44 $viewer = $this->getViewer(); ··· 99 58 100 59 $view->addProperty(pht('Automation'), $blueprint_view); 101 60 102 - return $this->newBox(pht('Automation'), $view); 61 + $can_edit = PhabricatorPolicyFilter::hasCapability( 62 + $viewer, 63 + $repository, 64 + PhabricatorPolicyCapability::CAN_EDIT); 65 + 66 + $can_test = $can_edit && $repository->canPerformAutomation(); 67 + 68 + $automation_uri = $this->getEditPageURI(); 69 + $test_uri = $repository->getPathURI('edit/testautomation/'); 70 + 71 + $edit = id(new PHUIButtonView()) 72 + ->setTag('a') 73 + ->setIcon('fa-pencil') 74 + ->setText(pht('Edit')) 75 + ->setHref($automation_uri) 76 + ->setDisabled(!$can_edit) 77 + ->setWorkflow(!$can_edit); 78 + 79 + $test = id(new PHUIButtonView()) 80 + ->setTag('a') 81 + ->setIcon('fa-gamepad') 82 + ->setText(pht('Test Config')) 83 + ->setWorkflow(true) 84 + ->setDisabled(!$can_test) 85 + ->setHref($test_uri); 86 + 87 + return $this->newBox(pht('Automation'), $view, array($edit, $test)); 103 88 } 104 89 105 90 }
+491 -26
src/applications/diffusion/management/DiffusionRepositoryBasicsManagementPanel.php
··· 14 14 } 15 15 16 16 public function getManagementPanelIcon() { 17 - $repository = $this->getRepository(); 18 - 19 - if (!$repository->isTracked()) { 20 - return 'fa-ban indigo'; 21 - } else { 22 - return 'fa-code'; 23 - } 17 + return 'fa-code'; 24 18 } 25 19 26 20 protected function getEditEngineFieldKeys() { ··· 33 27 ); 34 28 } 35 29 36 - public function buildManagementPanelCurtain() { 30 + private function buildActionMenu() { 37 31 $repository = $this->getRepository(); 38 32 $viewer = $this->getViewer(); 39 - $action_list = $this->getNewActionList(); 33 + $action_list = id(new PhabricatorActionListView()) 34 + ->setViewer($viewer); 40 35 41 36 $can_edit = PhabricatorPolicyFilter::hasCapability( 42 37 $viewer, ··· 50 45 $dangerous_uri = $repository->getPathURI('edit/dangerous/'); 51 46 52 47 if ($repository->isTracked()) { 53 - $activate_icon = 'fa-pause'; 54 48 $activate_label = pht('Deactivate Repository'); 55 49 } else { 56 - $activate_icon = 'fa-play'; 57 50 $activate_label = pht('Activate Repository'); 58 51 } 59 52 60 53 $should_dangerous = $repository->shouldAllowDangerousChanges(); 61 54 if ($should_dangerous) { 62 - $dangerous_icon = 'fa-shield'; 63 55 $dangerous_name = pht('Prevent Dangerous Changes'); 64 56 $can_dangerous = $can_edit; 65 57 } else { 66 - $dangerous_icon = 'fa-bullseye'; 67 58 $dangerous_name = pht('Allow Dangerous Changes'); 68 59 $can_dangerous = ($can_edit && $repository->canAllowDangerousChanges()); 69 60 } 70 61 71 62 $action_list->addAction( 72 63 id(new PhabricatorActionView()) 73 - ->setIcon('fa-pencil') 74 64 ->setName(pht('Edit Basic Information')) 75 65 ->setHref($edit_uri) 76 66 ->setDisabled(!$can_edit) ··· 78 68 79 69 $action_list->addAction( 80 70 id(new PhabricatorActionView()) 81 - ->setIcon('fa-text-width') 82 71 ->setName(pht('Edit Text Encoding')) 83 72 ->setHref($encoding_uri) 84 73 ->setDisabled(!$can_edit) ··· 86 75 87 76 $action_list->addAction( 88 77 id(new PhabricatorActionView()) 89 - ->setIcon($dangerous_icon) 90 78 ->setName($dangerous_name) 91 79 ->setHref($dangerous_uri) 92 80 ->setDisabled(!$can_dangerous) ··· 95 83 $action_list->addAction( 96 84 id(new PhabricatorActionView()) 97 85 ->setHref($activate_uri) 98 - ->setIcon($activate_icon) 99 86 ->setName($activate_label) 100 87 ->setDisabled(!$can_edit) 101 88 ->setWorkflow(true)); 89 + 90 + $action_list->addAction( 91 + id(new PhabricatorActionView()) 92 + ->setType(PhabricatorActionView::TYPE_DIVIDER)); 102 93 103 94 $action_list->addAction( 104 95 id(new PhabricatorActionView()) 105 96 ->setName(pht('Delete Repository')) 106 - ->setIcon('fa-times') 107 97 ->setHref($delete_uri) 98 + ->setColor(PhabricatorActionView::RED) 108 99 ->setDisabled(true) 109 100 ->setWorkflow(true)); 110 101 111 - return $this->getNewCurtainView($action_list); 102 + return $action_list; 112 103 } 113 104 114 105 public function buildManagementPanelContent() { 115 - $result = array(); 106 + 107 + $button = id(new PHUIButtonView()) 108 + ->setTag('a') 109 + ->setText(pht('Actions')) 110 + ->setHref('#') 111 + ->setIcon('fa-bars') 112 + ->addClass('phui-mobile-menu') 113 + ->setDropdownMenu($this->buildActionMenu()); 116 114 117 - $basics = $this->newBox(pht('Repository Basics'), $this->buildBasics()); 115 + $basics = $this->buildBasics(); 116 + $basics = $this->newBox(pht('Properties'), $basics, array($button)); 118 117 119 118 $repository = $this->getRepository(); 120 119 $is_new = $repository->isNewlyInitialized(); ··· 144 143 ->setErrors($messages); 145 144 } 146 145 147 - $result[] = $basics; 148 - 149 146 $description = $this->buildDescription(); 150 147 if ($description) { 151 - $result[] = $this->newBox(pht('Description'), $description); 148 + $description = $this->newBox(pht('Description'), $description); 152 149 } 150 + $status = $this->buildStatus(); 153 151 154 - return array($info_view, $result); 152 + return array($info_view, $basics, $description, $status); 155 153 } 156 154 157 155 private function buildBasics() { ··· 213 211 $view = id(new PHUIPropertyListView()) 214 212 ->setViewer($viewer); 215 213 if (!strlen($description)) { 216 - $description = phutil_tag('em', array(), pht('No description provided.')); 214 + return null; 217 215 } else { 218 216 $description = new PHUIRemarkupView($viewer, $description); 219 217 } 220 218 $view->addTextContent($description); 221 219 222 220 return $view; 221 + } 222 + 223 + private function buildStatus() { 224 + $repository = $this->getRepository(); 225 + $viewer = $this->getViewer(); 226 + $update_uri = $repository->getPathURI('edit/update/'); 227 + 228 + $view = id(new PHUIPropertyListView()) 229 + ->setViewer($viewer); 230 + 231 + $view->addProperty( 232 + pht('Update Frequency'), 233 + $this->buildRepositoryUpdateInterval($repository)); 234 + 235 + $messages = $this->loadStatusMessages($repository); 236 + 237 + $status = $this->buildRepositoryStatus($repository, $messages); 238 + $raw_error = $this->buildRepositoryRawError($repository, $messages); 239 + 240 + $view->addProperty(pht('Status'), $status); 241 + if ($raw_error) { 242 + $view->addSectionHeader(pht('Raw Error')); 243 + $view->addTextContent($raw_error); 244 + } 245 + 246 + $can_edit = PhabricatorPolicyFilter::hasCapability( 247 + $viewer, 248 + $repository, 249 + PhabricatorPolicyCapability::CAN_EDIT); 250 + 251 + $button = id(new PHUIButtonView()) 252 + ->setTag('a') 253 + ->setIcon('fa-refresh') 254 + ->setText(pht('Update Now')) 255 + ->setWorkflow(true) 256 + ->setDisabled(!$can_edit) 257 + ->setHref($update_uri); 258 + 259 + return $this->newBox(pht('Status'), $view, array($button)); 260 + } 261 + 262 + private function buildRepositoryUpdateInterval( 263 + PhabricatorRepository $repository) { 264 + 265 + $smart_wait = $repository->loadUpdateInterval(); 266 + 267 + $doc_href = PhabricatorEnv::getDoclink( 268 + 'Diffusion User Guide: Repository Updates'); 269 + 270 + return array( 271 + phutil_format_relative_time_detailed($smart_wait), 272 + " \xC2\xB7 ", 273 + phutil_tag( 274 + 'a', 275 + array( 276 + 'href' => $doc_href, 277 + 'target' => '_blank', 278 + ), 279 + pht('Learn More')), 280 + ); 281 + } 282 + 283 + private function buildRepositoryStatus( 284 + PhabricatorRepository $repository, 285 + array $messages) { 286 + 287 + $viewer = $this->getViewer(); 288 + $is_cluster = $repository->getAlmanacServicePHID(); 289 + 290 + $view = new PHUIStatusListView(); 291 + 292 + if ($repository->isTracked()) { 293 + $view->addItem( 294 + id(new PHUIStatusItemView()) 295 + ->setIcon(PHUIStatusItemView::ICON_ACCEPT, 'green') 296 + ->setTarget(pht('Repository Active'))); 297 + } else { 298 + $view->addItem( 299 + id(new PHUIStatusItemView()) 300 + ->setIcon(PHUIStatusItemView::ICON_WARNING, 'bluegrey') 301 + ->setTarget(pht('Repository Inactive')) 302 + ->setNote( 303 + pht('Activate this repository to begin or resume import.'))); 304 + return $view; 305 + } 306 + 307 + $binaries = array(); 308 + $svnlook_check = false; 309 + switch ($repository->getVersionControlSystem()) { 310 + case PhabricatorRepositoryType::REPOSITORY_TYPE_GIT: 311 + $binaries[] = 'git'; 312 + break; 313 + case PhabricatorRepositoryType::REPOSITORY_TYPE_SVN: 314 + $binaries[] = 'svn'; 315 + break; 316 + case PhabricatorRepositoryType::REPOSITORY_TYPE_MERCURIAL: 317 + $binaries[] = 'hg'; 318 + break; 319 + } 320 + 321 + if ($repository->isHosted()) { 322 + $proto_https = PhabricatorRepositoryURI::BUILTIN_PROTOCOL_HTTPS; 323 + $proto_http = PhabricatorRepositoryURI::BUILTIN_PROTOCOL_HTTP; 324 + $can_http = $repository->canServeProtocol($proto_http, false) || 325 + $repository->canServeProtocol($proto_https, false); 326 + 327 + if ($can_http) { 328 + switch ($repository->getVersionControlSystem()) { 329 + case PhabricatorRepositoryType::REPOSITORY_TYPE_GIT: 330 + $binaries[] = 'git-http-backend'; 331 + break; 332 + case PhabricatorRepositoryType::REPOSITORY_TYPE_SVN: 333 + $binaries[] = 'svnserve'; 334 + $binaries[] = 'svnadmin'; 335 + $binaries[] = 'svnlook'; 336 + $svnlook_check = true; 337 + break; 338 + case PhabricatorRepositoryType::REPOSITORY_TYPE_MERCURIAL: 339 + $binaries[] = 'hg'; 340 + break; 341 + } 342 + } 343 + 344 + 345 + $proto_ssh = PhabricatorRepositoryURI::BUILTIN_PROTOCOL_SSH; 346 + $can_ssh = $repository->canServeProtocol($proto_ssh, false); 347 + 348 + if ($can_ssh) { 349 + switch ($repository->getVersionControlSystem()) { 350 + case PhabricatorRepositoryType::REPOSITORY_TYPE_GIT: 351 + $binaries[] = 'git-receive-pack'; 352 + $binaries[] = 'git-upload-pack'; 353 + break; 354 + case PhabricatorRepositoryType::REPOSITORY_TYPE_SVN: 355 + $binaries[] = 'svnserve'; 356 + $binaries[] = 'svnadmin'; 357 + $binaries[] = 'svnlook'; 358 + $svnlook_check = true; 359 + break; 360 + case PhabricatorRepositoryType::REPOSITORY_TYPE_MERCURIAL: 361 + $binaries[] = 'hg'; 362 + break; 363 + } 364 + } 365 + } 366 + 367 + $binaries = array_unique($binaries); 368 + if (!$is_cluster) { 369 + // We're only checking for binaries if we aren't running with a cluster 370 + // configuration. In theory, we could check for binaries on the 371 + // repository host machine, but we'd need to make this more complicated 372 + // to do that. 373 + 374 + foreach ($binaries as $binary) { 375 + $where = Filesystem::resolveBinary($binary); 376 + if (!$where) { 377 + $view->addItem( 378 + id(new PHUIStatusItemView()) 379 + ->setIcon(PHUIStatusItemView::ICON_WARNING, 'red') 380 + ->setTarget( 381 + pht('Missing Binary %s', phutil_tag('tt', array(), $binary))) 382 + ->setNote(pht( 383 + "Unable to find this binary in the webserver's PATH. You may ". 384 + "need to configure %s.", 385 + $this->getEnvConfigLink()))); 386 + } else { 387 + $view->addItem( 388 + id(new PHUIStatusItemView()) 389 + ->setIcon(PHUIStatusItemView::ICON_ACCEPT, 'green') 390 + ->setTarget( 391 + pht('Found Binary %s', phutil_tag('tt', array(), $binary))) 392 + ->setNote(phutil_tag('tt', array(), $where))); 393 + } 394 + } 395 + 396 + // This gets checked generically above. However, for svn commit hooks, we 397 + // need this to be in environment.append-paths because subversion strips 398 + // PATH. 399 + if ($svnlook_check) { 400 + $where = Filesystem::resolveBinary('svnlook'); 401 + if ($where) { 402 + $path = substr($where, 0, strlen($where) - strlen('svnlook')); 403 + $dirs = PhabricatorEnv::getEnvConfig('environment.append-paths'); 404 + $in_path = false; 405 + foreach ($dirs as $dir) { 406 + if (Filesystem::isDescendant($path, $dir)) { 407 + $in_path = true; 408 + break; 409 + } 410 + } 411 + if (!$in_path) { 412 + $view->addItem( 413 + id(new PHUIStatusItemView()) 414 + ->setIcon(PHUIStatusItemView::ICON_WARNING, 'red') 415 + ->setTarget( 416 + pht('Missing Binary %s', phutil_tag('tt', array(), $binary))) 417 + ->setNote(pht( 418 + 'Unable to find this binary in `%s`. '. 419 + 'You need to configure %s and include %s.', 420 + 'environment.append-paths', 421 + $this->getEnvConfigLink(), 422 + $path))); 423 + } 424 + } 425 + } 426 + } 427 + 428 + $doc_href = PhabricatorEnv::getDoclink('Managing Daemons with phd'); 429 + 430 + $daemon_instructions = pht( 431 + 'Use %s to start daemons. See %s.', 432 + phutil_tag('tt', array(), 'bin/phd start'), 433 + phutil_tag( 434 + 'a', 435 + array( 436 + 'href' => $doc_href, 437 + ), 438 + pht('Managing Daemons with phd'))); 439 + 440 + 441 + $pull_daemon = id(new PhabricatorDaemonLogQuery()) 442 + ->setViewer(PhabricatorUser::getOmnipotentUser()) 443 + ->withStatus(PhabricatorDaemonLogQuery::STATUS_ALIVE) 444 + ->withDaemonClasses(array('PhabricatorRepositoryPullLocalDaemon')) 445 + ->setLimit(1) 446 + ->execute(); 447 + 448 + if ($pull_daemon) { 449 + 450 + // TODO: In a cluster environment, we need a daemon on this repository's 451 + // host, specifically, and we aren't checking for that right now. This 452 + // is a reasonable proxy for things being more-or-less correctly set up, 453 + // though. 454 + 455 + $view->addItem( 456 + id(new PHUIStatusItemView()) 457 + ->setIcon(PHUIStatusItemView::ICON_ACCEPT, 'green') 458 + ->setTarget(pht('Pull Daemon Running'))); 459 + } else { 460 + $view->addItem( 461 + id(new PHUIStatusItemView()) 462 + ->setIcon(PHUIStatusItemView::ICON_WARNING, 'red') 463 + ->setTarget(pht('Pull Daemon Not Running')) 464 + ->setNote($daemon_instructions)); 465 + } 466 + 467 + 468 + $task_daemon = id(new PhabricatorDaemonLogQuery()) 469 + ->setViewer(PhabricatorUser::getOmnipotentUser()) 470 + ->withStatus(PhabricatorDaemonLogQuery::STATUS_ALIVE) 471 + ->withDaemonClasses(array('PhabricatorTaskmasterDaemon')) 472 + ->setLimit(1) 473 + ->execute(); 474 + if ($task_daemon) { 475 + $view->addItem( 476 + id(new PHUIStatusItemView()) 477 + ->setIcon(PHUIStatusItemView::ICON_ACCEPT, 'green') 478 + ->setTarget(pht('Task Daemon Running'))); 479 + } else { 480 + $view->addItem( 481 + id(new PHUIStatusItemView()) 482 + ->setIcon(PHUIStatusItemView::ICON_WARNING, 'red') 483 + ->setTarget(pht('Task Daemon Not Running')) 484 + ->setNote($daemon_instructions)); 485 + } 486 + 487 + 488 + if ($is_cluster) { 489 + // Just omit this status check for now in cluster environments. We 490 + // could make a service call and pull it from the repository host 491 + // eventually. 492 + } else if ($repository->usesLocalWorkingCopy()) { 493 + $local_parent = dirname($repository->getLocalPath()); 494 + if (Filesystem::pathExists($local_parent)) { 495 + $view->addItem( 496 + id(new PHUIStatusItemView()) 497 + ->setIcon(PHUIStatusItemView::ICON_ACCEPT, 'green') 498 + ->setTarget(pht('Storage Directory OK')) 499 + ->setNote(phutil_tag('tt', array(), $local_parent))); 500 + } else { 501 + $view->addItem( 502 + id(new PHUIStatusItemView()) 503 + ->setIcon(PHUIStatusItemView::ICON_WARNING, 'red') 504 + ->setTarget(pht('No Storage Directory')) 505 + ->setNote( 506 + pht( 507 + 'Storage directory %s does not exist, or is not readable by '. 508 + 'the webserver. Create this directory or make it readable.', 509 + phutil_tag('tt', array(), $local_parent)))); 510 + return $view; 511 + } 512 + 513 + $local_path = $repository->getLocalPath(); 514 + $message = idx($messages, PhabricatorRepositoryStatusMessage::TYPE_INIT); 515 + if ($message) { 516 + switch ($message->getStatusCode()) { 517 + case PhabricatorRepositoryStatusMessage::CODE_ERROR: 518 + $view->addItem( 519 + id(new PHUIStatusItemView()) 520 + ->setIcon(PHUIStatusItemView::ICON_WARNING, 'red') 521 + ->setTarget(pht('Initialization Error')) 522 + ->setNote($message->getParameter('message'))); 523 + return $view; 524 + case PhabricatorRepositoryStatusMessage::CODE_OKAY: 525 + if (Filesystem::pathExists($local_path)) { 526 + $view->addItem( 527 + id(new PHUIStatusItemView()) 528 + ->setIcon(PHUIStatusItemView::ICON_ACCEPT, 'green') 529 + ->setTarget(pht('Working Copy OK')) 530 + ->setNote(phutil_tag('tt', array(), $local_path))); 531 + } else { 532 + $view->addItem( 533 + id(new PHUIStatusItemView()) 534 + ->setIcon(PHUIStatusItemView::ICON_WARNING, 'red') 535 + ->setTarget(pht('Working Copy Error')) 536 + ->setNote( 537 + pht( 538 + 'Working copy %s has been deleted, or is not '. 539 + 'readable by the webserver. Make this directory '. 540 + 'readable. If it has been deleted, the daemons should '. 541 + 'restore it automatically.', 542 + phutil_tag('tt', array(), $local_path)))); 543 + return $view; 544 + } 545 + break; 546 + default: 547 + $view->addItem( 548 + id(new PHUIStatusItemView()) 549 + ->setIcon(PHUIStatusItemView::ICON_CLOCK, 'green') 550 + ->setTarget(pht('Initializing Working Copy')) 551 + ->setNote(pht('Daemons are initializing the working copy.'))); 552 + return $view; 553 + } 554 + } else { 555 + $view->addItem( 556 + id(new PHUIStatusItemView()) 557 + ->setIcon(PHUIStatusItemView::ICON_CLOCK, 'orange') 558 + ->setTarget(pht('No Working Copy Yet')) 559 + ->setNote( 560 + pht('Waiting for daemons to build a working copy.'))); 561 + return $view; 562 + } 563 + } 564 + 565 + $message = idx($messages, PhabricatorRepositoryStatusMessage::TYPE_FETCH); 566 + if ($message) { 567 + switch ($message->getStatusCode()) { 568 + case PhabricatorRepositoryStatusMessage::CODE_ERROR: 569 + $message = $message->getParameter('message'); 570 + 571 + $suggestion = null; 572 + if (preg_match('/Permission denied \(publickey\)./', $message)) { 573 + $suggestion = pht( 574 + 'Public Key Error: This error usually indicates that the '. 575 + 'keypair you have configured does not have permission to '. 576 + 'access the repository.'); 577 + } 578 + 579 + $view->addItem( 580 + id(new PHUIStatusItemView()) 581 + ->setIcon(PHUIStatusItemView::ICON_WARNING, 'red') 582 + ->setTarget(pht('Update Error')) 583 + ->setNote($suggestion)); 584 + return $view; 585 + case PhabricatorRepositoryStatusMessage::CODE_OKAY: 586 + $ago = (PhabricatorTime::getNow() - $message->getEpoch()); 587 + $view->addItem( 588 + id(new PHUIStatusItemView()) 589 + ->setIcon(PHUIStatusItemView::ICON_ACCEPT, 'green') 590 + ->setTarget(pht('Updates OK')) 591 + ->setNote( 592 + pht( 593 + 'Last updated %s (%s ago).', 594 + phabricator_datetime($message->getEpoch(), $viewer), 595 + phutil_format_relative_time_detailed($ago)))); 596 + break; 597 + } 598 + } else { 599 + $view->addItem( 600 + id(new PHUIStatusItemView()) 601 + ->setIcon(PHUIStatusItemView::ICON_CLOCK, 'orange') 602 + ->setTarget(pht('Waiting For Update')) 603 + ->setNote( 604 + pht('Waiting for daemons to read updates.'))); 605 + } 606 + 607 + if ($repository->isImporting()) { 608 + $ratio = $repository->loadImportProgress(); 609 + $percentage = sprintf('%.2f%%', 100 * $ratio); 610 + 611 + $view->addItem( 612 + id(new PHUIStatusItemView()) 613 + ->setIcon(PHUIStatusItemView::ICON_CLOCK, 'green') 614 + ->setTarget(pht('Importing')) 615 + ->setNote( 616 + pht('%s Complete', $percentage))); 617 + } else { 618 + $view->addItem( 619 + id(new PHUIStatusItemView()) 620 + ->setIcon(PHUIStatusItemView::ICON_ACCEPT, 'green') 621 + ->setTarget(pht('Fully Imported'))); 622 + } 623 + 624 + if (idx($messages, PhabricatorRepositoryStatusMessage::TYPE_NEEDS_UPDATE)) { 625 + $view->addItem( 626 + id(new PHUIStatusItemView()) 627 + ->setIcon(PHUIStatusItemView::ICON_UP, 'indigo') 628 + ->setTarget(pht('Prioritized')) 629 + ->setNote(pht('This repository will be updated soon!'))); 630 + } 631 + 632 + return $view; 633 + } 634 + 635 + private function buildRepositoryRawError( 636 + PhabricatorRepository $repository, 637 + array $messages) { 638 + $viewer = $this->getViewer(); 639 + 640 + $can_edit = PhabricatorPolicyFilter::hasCapability( 641 + $viewer, 642 + $repository, 643 + PhabricatorPolicyCapability::CAN_EDIT); 644 + 645 + $raw_error = null; 646 + 647 + $message = idx($messages, PhabricatorRepositoryStatusMessage::TYPE_FETCH); 648 + if ($message) { 649 + switch ($message->getStatusCode()) { 650 + case PhabricatorRepositoryStatusMessage::CODE_ERROR: 651 + $raw_error = $message->getParameter('message'); 652 + break; 653 + } 654 + } 655 + 656 + if ($raw_error !== null) { 657 + if (!$can_edit) { 658 + $raw_message = pht( 659 + 'You must be able to edit a repository to see raw error messages '. 660 + 'because they sometimes disclose sensitive information.'); 661 + $raw_message = phutil_tag('em', array(), $raw_message); 662 + } else { 663 + $raw_message = phutil_escape_html_newlines($raw_error); 664 + } 665 + } else { 666 + $raw_message = null; 667 + } 668 + 669 + return $raw_message; 670 + } 671 + 672 + private function loadStatusMessages(PhabricatorRepository $repository) { 673 + $messages = id(new PhabricatorRepositoryStatusMessage()) 674 + ->loadAllWhere('repositoryID = %d', $repository->getID()); 675 + $messages = mpull($messages, null, 'getStatusType'); 676 + 677 + return $messages; 678 + } 679 + 680 + private function getEnvConfigLink() { 681 + $config_href = '/config/edit/environment.append-paths/'; 682 + return phutil_tag( 683 + 'a', 684 + array( 685 + 'href' => $config_href, 686 + ), 687 + 'environment.append-paths'); 223 688 } 224 689 225 690 }
+20 -41
src/applications/diffusion/management/DiffusionRepositoryBranchesManagementPanel.php
··· 19 19 } 20 20 21 21 public function getManagementPanelIcon() { 22 - $repository = $this->getRepository(); 23 - 24 - $has_any = 25 - $repository->getDetail('default-branch') || 26 - $repository->getDetail('branch-filter') || 27 - $repository->getDetail('close-commits-filter'); 28 - 29 - if ($has_any) { 30 - return 'fa-code-fork'; 31 - } else { 32 - return 'fa-code-fork grey'; 33 - } 22 + return 'fa-code-fork'; 34 23 } 35 24 36 25 protected function getEditEngineFieldKeys() { ··· 41 30 ); 42 31 } 43 32 44 - public function buildManagementPanelCurtain() { 45 - $repository = $this->getRepository(); 46 - $viewer = $this->getViewer(); 47 - $action_list = $this->getNewActionList(); 48 - 49 - $can_edit = PhabricatorPolicyFilter::hasCapability( 50 - $viewer, 51 - $repository, 52 - PhabricatorPolicyCapability::CAN_EDIT); 53 - 54 - $branches_uri = $this->getEditPageURI(); 55 - 56 - $action_list->addAction( 57 - id(new PhabricatorActionView()) 58 - ->setIcon('fa-pencil') 59 - ->setName(pht('Edit Branches')) 60 - ->setHref($branches_uri) 61 - ->setDisabled(!$can_edit) 62 - ->setWorkflow(!$can_edit)); 63 - 64 - return $this->getNewCurtainView($action_list); 65 - } 66 - 67 33 public function buildManagementPanelContent() { 68 34 $repository = $this->getRepository(); 69 35 $viewer = $this->getViewer(); ··· 94 60 } 95 61 96 62 $view->addProperty(pht('Autoclose Only'), $autoclose_only); 97 - $content[] = $this->newBox(pht('Branches'), $view); 63 + 64 + $can_edit = PhabricatorPolicyFilter::hasCapability( 65 + $viewer, 66 + $repository, 67 + PhabricatorPolicyCapability::CAN_EDIT); 68 + 69 + $branches_uri = $this->getEditPageURI(); 70 + 71 + $button = id(new PHUIButtonView()) 72 + ->setTag('a') 73 + ->setIcon('fa-pencil') 74 + ->setText(pht('Edit')) 75 + ->setHref($branches_uri) 76 + ->setDisabled(!$can_edit) 77 + ->setWorkflow(!$can_edit); 78 + 79 + $content[] = $this->newBox(pht('Branches'), $view, array($button)); 98 80 99 81 // Branch Autoclose Table 100 82 if (!$repository->isImporting()) { ··· 176 158 true, 177 159 )); 178 160 179 - $box = id(new PHUIObjectBoxView()) 180 - ->setHeaderText(pht('Branch Status')) 181 - ->setBackground(PHUIObjectBoxView::BLUE_PROPERTY) 182 - ->setTable($branch_table) 183 - ->setPager($pager); 161 + $box = $this->newBox(pht('Branch Status'), $branch_table); 162 + $box->setPager($pager); 184 163 $content[] = $box; 185 164 } else { 186 165 $content[] = id(new PHUIInfoView())
-33
src/applications/diffusion/management/DiffusionRepositoryDocumentationManagementPanel.php
··· 1 - <?php 2 - 3 - final class DiffusionRepositoryDocumentationManagementPanel 4 - extends DiffusionRepositoryManagementPanel { 5 - 6 - const PANELKEY = 'documentation'; 7 - 8 - public function getManagementPanelLabel() { 9 - return pht('Documentation'); 10 - } 11 - 12 - public function getManagementPanelOrder() { 13 - return 3000; 14 - } 15 - 16 - public function getManagementPanelIcon() { 17 - return 'fa-book'; 18 - } 19 - 20 - public function buildManagementPanelContent() { 21 - return null; 22 - } 23 - 24 - public function buildManagementPanelCurtain() { 25 - return null; 26 - } 27 - 28 - public function getPanelNavigationURI() { 29 - return PhabricatorEnv::getDoclink( 30 - 'Diffusion User Guide: Managing Repositories'); 31 - } 32 - 33 - }
-4
src/applications/diffusion/management/DiffusionRepositoryHistoryManagementPanel.php
··· 21 21 return $this->newTimeline(); 22 22 } 23 23 24 - public function buildManagementPanelCurtain() { 25 - return null; 26 - } 27 - 28 24 }
+13 -21
src/applications/diffusion/management/DiffusionRepositoryManagementPanel.php
··· 41 41 abstract public function getManagementPanelLabel(); 42 42 abstract public function getManagementPanelOrder(); 43 43 abstract public function buildManagementPanelContent(); 44 - abstract public function buildManagementPanelCurtain(); 45 44 46 45 public function getManagementPanelIcon() { 47 46 return 'fa-pencil'; ··· 54 53 public function shouldEnableForRepository( 55 54 PhabricatorRepository $repository) { 56 55 return true; 57 - } 58 - 59 - public function getNewActionList() { 60 - $viewer = $this->getViewer(); 61 - $action_id = celerity_generate_unique_node_id(); 62 - 63 - return id(new PhabricatorActionListView()) 64 - ->setViewer($viewer) 65 - ->setID($action_id); 66 - } 67 - 68 - public function getNewCurtainView(PhabricatorActionListView $action_list) { 69 - $viewer = $this->getViewer(); 70 - return id(new PHUICurtainView()) 71 - ->setViewer($viewer) 72 - ->setActionList($action_list); 73 56 } 74 57 75 58 public static function getAllPanels() { ··· 80 63 ->execute(); 81 64 } 82 65 83 - final protected function newBox($header_text, $body) { 84 - return id(new PHUIObjectBoxView()) 85 - ->setHeaderText($header_text) 86 - ->setBackground(PHUIObjectBoxView::BLUE_PROPERTY) 66 + final protected function newBox($header_text, $body, $button = array()) { 67 + $header = id(new PHUIHeaderView()) 68 + ->setHeader($header_text); 69 + 70 + foreach ($button as $link) { 71 + $header->addActionLink($link); 72 + } 73 + 74 + $view = id(new PHUIObjectBoxView()) 75 + ->setHeader($header) 76 + ->setBackground(PHUIObjectBoxView::WHITE_CONFIG) 87 77 ->appendChild($body); 78 + 79 + return $view; 88 80 } 89 81 90 82 final protected function newTimeline() {
+17 -53
src/applications/diffusion/management/DiffusionRepositoryPoliciesManagementPanel.php
··· 14 14 } 15 15 16 16 public function getManagementPanelIcon() { 17 - $viewer = $this->getViewer(); 18 - $repository = $this->getRepository(); 19 - 20 - $can_view = PhabricatorPolicyCapability::CAN_VIEW; 21 - $can_edit = PhabricatorPolicyCapability::CAN_EDIT; 22 - $can_push = DiffusionPushCapability::CAPABILITY; 23 - 24 - $actual_values = array( 25 - 'spacePHID' => $repository->getSpacePHID(), 26 - 'view' => $repository->getPolicy($can_view), 27 - 'edit' => $repository->getPolicy($can_edit), 28 - 'push' => $repository->getPolicy($can_push), 29 - ); 30 - 31 - $default = PhabricatorRepository::initializeNewRepository( 32 - $viewer); 33 - 34 - $default_values = array( 35 - 'spacePHID' => $default->getSpacePHID(), 36 - 'view' => $default->getPolicy($can_view), 37 - 'edit' => $default->getPolicy($can_edit), 38 - 'push' => $default->getPolicy($can_push), 39 - ); 40 - 41 - if ($actual_values === $default_values) { 42 - return 'fa-lock grey'; 43 - } else { 44 - return 'fa-lock'; 45 - } 17 + return 'fa-lock'; 46 18 } 47 19 48 20 protected function getEditEngineFieldKeys() { ··· 54 26 ); 55 27 } 56 28 57 - public function buildManagementPanelCurtain() { 58 - $repository = $this->getRepository(); 59 - $viewer = $this->getViewer(); 60 - $action_list = $this->getNewActionList(); 61 - 62 - $can_edit = PhabricatorPolicyFilter::hasCapability( 63 - $viewer, 64 - $repository, 65 - PhabricatorPolicyCapability::CAN_EDIT); 66 - 67 - $edit_uri = $this->getEditPageURI(); 68 - 69 - $action_list->addAction( 70 - id(new PhabricatorActionView()) 71 - ->setIcon('fa-pencil') 72 - ->setName(pht('Edit Policies')) 73 - ->setHref($edit_uri) 74 - ->setDisabled(!$can_edit) 75 - ->setWorkflow(!$can_edit)); 76 - 77 - return $this->getNewCurtainView($action_list); 78 - } 79 - 80 29 public function buildManagementPanelContent() { 81 30 $repository = $this->getRepository(); 82 31 $viewer = $this->getViewer(); ··· 109 58 : phutil_tag('em', array(), pht('Not a Hosted Repository')); 110 59 $view->addProperty(pht('Pushable By'), $pushable); 111 60 112 - return $this->newBox(pht('Policies'), $view); 61 + $can_edit = PhabricatorPolicyFilter::hasCapability( 62 + $viewer, 63 + $repository, 64 + PhabricatorPolicyCapability::CAN_EDIT); 65 + 66 + $edit_uri = $this->getEditPageURI(); 67 + 68 + $button = id(new PHUIButtonView()) 69 + ->setTag('a') 70 + ->setIcon('fa-pencil') 71 + ->setText(pht('Edit')) 72 + ->setHref($edit_uri) 73 + ->setDisabled(!$can_edit) 74 + ->setWorkflow(!$can_edit); 75 + 76 + return $this->newBox(pht('Policies'), $view, array($button)); 113 77 } 114 78 115 79 }
+17 -33
src/applications/diffusion/management/DiffusionRepositoryStagingManagementPanel.php
··· 20 20 21 21 22 22 public function getManagementPanelIcon() { 23 - $repository = $this->getRepository(); 24 - 25 - $staging_uri = $repository->getStagingURI(); 26 - 27 - if ($staging_uri) { 28 - return 'fa-upload'; 29 - } else { 30 - return 'fa-upload grey'; 31 - } 23 + return 'fa-upload'; 32 24 } 33 25 34 26 protected function getEditEngineFieldKeys() { ··· 37 29 ); 38 30 } 39 31 40 - public function buildManagementPanelCurtain() { 41 - $repository = $this->getRepository(); 42 - $viewer = $this->getViewer(); 43 - $action_list = $this->getNewActionList(); 44 - 45 - $can_edit = PhabricatorPolicyFilter::hasCapability( 46 - $viewer, 47 - $repository, 48 - PhabricatorPolicyCapability::CAN_EDIT); 49 - 50 - $staging_uri = $this->getEditPageURI(); 51 - 52 - $action_list->addAction( 53 - id(new PhabricatorActionView()) 54 - ->setIcon('fa-pencil') 55 - ->setName(pht('Edit Staging')) 56 - ->setHref($staging_uri) 57 - ->setDisabled(!$can_edit) 58 - ->setWorkflow(!$can_edit)); 59 - 60 - return $this->getNewCurtainView($action_list); 61 - } 62 - 63 32 public function buildManagementPanelContent() { 64 33 $repository = $this->getRepository(); 65 34 $viewer = $this->getViewer(); ··· 74 43 75 44 $view->addProperty(pht('Staging Area URI'), $staging_uri); 76 45 77 - return $this->newBox(pht('Staging Area'), $view); 46 + $can_edit = PhabricatorPolicyFilter::hasCapability( 47 + $viewer, 48 + $repository, 49 + PhabricatorPolicyCapability::CAN_EDIT); 50 + 51 + $staging_uri = $this->getEditPageURI(); 52 + 53 + $button = id(new PHUIButtonView()) 54 + ->setTag('a') 55 + ->setIcon('fa-pencil') 56 + ->setText(pht('Edit')) 57 + ->setHref($staging_uri) 58 + ->setDisabled(!$can_edit) 59 + ->setWorkflow(!$can_edit); 60 + 61 + return $this->newBox(pht('Staging Area'), $view, array($button)); 78 62 } 79 63 80 64 }
-507
src/applications/diffusion/management/DiffusionRepositoryStatusManagementPanel.php
··· 1 - <?php 2 - 3 - final class DiffusionRepositoryStatusManagementPanel 4 - extends DiffusionRepositoryManagementPanel { 5 - 6 - const PANELKEY = 'status'; 7 - 8 - public function getManagementPanelLabel() { 9 - return pht('Status'); 10 - } 11 - 12 - public function getManagementPanelOrder() { 13 - return 200; 14 - } 15 - 16 - public function getManagementPanelIcon() { 17 - $repository = $this->getRepository(); 18 - 19 - // TODO: We could try to show a warning icon in more cases, but just 20 - // raise in the most serious cases for now. 21 - $messages = $this->loadStatusMessages($repository); 22 - 23 - $raw_error = $this->buildRepositoryRawError($repository, $messages); 24 - if ($raw_error) { 25 - return 'fa-exclamation-triangle red'; 26 - } 27 - 28 - return 'fa-check grey'; 29 - } 30 - 31 - public function buildManagementPanelCurtain() { 32 - $repository = $this->getRepository(); 33 - $viewer = $this->getViewer(); 34 - $action_list = $this->getNewActionList(); 35 - 36 - $can_edit = PhabricatorPolicyFilter::hasCapability( 37 - $viewer, 38 - $repository, 39 - PhabricatorPolicyCapability::CAN_EDIT); 40 - 41 - $update_uri = $repository->getPathURI('edit/update/'); 42 - 43 - $action_list->addAction( 44 - id(new PhabricatorActionView()) 45 - ->setIcon('fa-refresh') 46 - ->setName(pht('Update Now')) 47 - ->setWorkflow(true) 48 - ->setDisabled(!$can_edit) 49 - ->setHref($update_uri)); 50 - 51 - return $this->getNewCurtainView($action_list); 52 - } 53 - 54 - public function buildManagementPanelContent() { 55 - $repository = $this->getRepository(); 56 - $viewer = $this->getViewer(); 57 - 58 - $view = id(new PHUIPropertyListView()) 59 - ->setViewer($viewer); 60 - 61 - $view->addProperty( 62 - pht('Update Frequency'), 63 - $this->buildRepositoryUpdateInterval($repository)); 64 - 65 - $messages = $this->loadStatusMessages($repository); 66 - 67 - $status = $this->buildRepositoryStatus($repository, $messages); 68 - $raw_error = $this->buildRepositoryRawError($repository, $messages); 69 - 70 - $view->addProperty(pht('Status'), $status); 71 - if ($raw_error) { 72 - $view->addSectionHeader(pht('Raw Error')); 73 - $view->addTextContent($raw_error); 74 - } 75 - 76 - return $this->newBox(pht('Status'), $view); 77 - } 78 - 79 - private function buildRepositoryUpdateInterval( 80 - PhabricatorRepository $repository) { 81 - 82 - $smart_wait = $repository->loadUpdateInterval(); 83 - 84 - $doc_href = PhabricatorEnv::getDoclink( 85 - 'Diffusion User Guide: Repository Updates'); 86 - 87 - return array( 88 - phutil_format_relative_time_detailed($smart_wait), 89 - " \xC2\xB7 ", 90 - phutil_tag( 91 - 'a', 92 - array( 93 - 'href' => $doc_href, 94 - 'target' => '_blank', 95 - ), 96 - pht('Learn More')), 97 - ); 98 - } 99 - 100 - private function buildRepositoryStatus( 101 - PhabricatorRepository $repository, 102 - array $messages) { 103 - 104 - $viewer = $this->getViewer(); 105 - $is_cluster = $repository->getAlmanacServicePHID(); 106 - 107 - $view = new PHUIStatusListView(); 108 - 109 - if ($repository->isTracked()) { 110 - $view->addItem( 111 - id(new PHUIStatusItemView()) 112 - ->setIcon(PHUIStatusItemView::ICON_ACCEPT, 'green') 113 - ->setTarget(pht('Repository Active'))); 114 - } else { 115 - $view->addItem( 116 - id(new PHUIStatusItemView()) 117 - ->setIcon(PHUIStatusItemView::ICON_WARNING, 'bluegrey') 118 - ->setTarget(pht('Repository Inactive')) 119 - ->setNote( 120 - pht('Activate this repository to begin or resume import.'))); 121 - return $view; 122 - } 123 - 124 - $binaries = array(); 125 - $svnlook_check = false; 126 - switch ($repository->getVersionControlSystem()) { 127 - case PhabricatorRepositoryType::REPOSITORY_TYPE_GIT: 128 - $binaries[] = 'git'; 129 - break; 130 - case PhabricatorRepositoryType::REPOSITORY_TYPE_SVN: 131 - $binaries[] = 'svn'; 132 - break; 133 - case PhabricatorRepositoryType::REPOSITORY_TYPE_MERCURIAL: 134 - $binaries[] = 'hg'; 135 - break; 136 - } 137 - 138 - if ($repository->isHosted()) { 139 - $proto_https = PhabricatorRepositoryURI::BUILTIN_PROTOCOL_HTTPS; 140 - $proto_http = PhabricatorRepositoryURI::BUILTIN_PROTOCOL_HTTP; 141 - $can_http = $repository->canServeProtocol($proto_http, false) || 142 - $repository->canServeProtocol($proto_https, false); 143 - 144 - if ($can_http) { 145 - switch ($repository->getVersionControlSystem()) { 146 - case PhabricatorRepositoryType::REPOSITORY_TYPE_GIT: 147 - $binaries[] = 'git-http-backend'; 148 - break; 149 - case PhabricatorRepositoryType::REPOSITORY_TYPE_SVN: 150 - $binaries[] = 'svnserve'; 151 - $binaries[] = 'svnadmin'; 152 - $binaries[] = 'svnlook'; 153 - $svnlook_check = true; 154 - break; 155 - case PhabricatorRepositoryType::REPOSITORY_TYPE_MERCURIAL: 156 - $binaries[] = 'hg'; 157 - break; 158 - } 159 - } 160 - 161 - 162 - $proto_ssh = PhabricatorRepositoryURI::BUILTIN_PROTOCOL_SSH; 163 - $can_ssh = $repository->canServeProtocol($proto_ssh, false); 164 - 165 - if ($can_ssh) { 166 - switch ($repository->getVersionControlSystem()) { 167 - case PhabricatorRepositoryType::REPOSITORY_TYPE_GIT: 168 - $binaries[] = 'git-receive-pack'; 169 - $binaries[] = 'git-upload-pack'; 170 - break; 171 - case PhabricatorRepositoryType::REPOSITORY_TYPE_SVN: 172 - $binaries[] = 'svnserve'; 173 - $binaries[] = 'svnadmin'; 174 - $binaries[] = 'svnlook'; 175 - $svnlook_check = true; 176 - break; 177 - case PhabricatorRepositoryType::REPOSITORY_TYPE_MERCURIAL: 178 - $binaries[] = 'hg'; 179 - break; 180 - } 181 - } 182 - } 183 - 184 - $binaries = array_unique($binaries); 185 - if (!$is_cluster) { 186 - // We're only checking for binaries if we aren't running with a cluster 187 - // configuration. In theory, we could check for binaries on the 188 - // repository host machine, but we'd need to make this more complicated 189 - // to do that. 190 - 191 - foreach ($binaries as $binary) { 192 - $where = Filesystem::resolveBinary($binary); 193 - if (!$where) { 194 - $view->addItem( 195 - id(new PHUIStatusItemView()) 196 - ->setIcon(PHUIStatusItemView::ICON_WARNING, 'red') 197 - ->setTarget( 198 - pht('Missing Binary %s', phutil_tag('tt', array(), $binary))) 199 - ->setNote(pht( 200 - "Unable to find this binary in the webserver's PATH. You may ". 201 - "need to configure %s.", 202 - $this->getEnvConfigLink()))); 203 - } else { 204 - $view->addItem( 205 - id(new PHUIStatusItemView()) 206 - ->setIcon(PHUIStatusItemView::ICON_ACCEPT, 'green') 207 - ->setTarget( 208 - pht('Found Binary %s', phutil_tag('tt', array(), $binary))) 209 - ->setNote(phutil_tag('tt', array(), $where))); 210 - } 211 - } 212 - 213 - // This gets checked generically above. However, for svn commit hooks, we 214 - // need this to be in environment.append-paths because subversion strips 215 - // PATH. 216 - if ($svnlook_check) { 217 - $where = Filesystem::resolveBinary('svnlook'); 218 - if ($where) { 219 - $path = substr($where, 0, strlen($where) - strlen('svnlook')); 220 - $dirs = PhabricatorEnv::getEnvConfig('environment.append-paths'); 221 - $in_path = false; 222 - foreach ($dirs as $dir) { 223 - if (Filesystem::isDescendant($path, $dir)) { 224 - $in_path = true; 225 - break; 226 - } 227 - } 228 - if (!$in_path) { 229 - $view->addItem( 230 - id(new PHUIStatusItemView()) 231 - ->setIcon(PHUIStatusItemView::ICON_WARNING, 'red') 232 - ->setTarget( 233 - pht('Missing Binary %s', phutil_tag('tt', array(), $binary))) 234 - ->setNote(pht( 235 - 'Unable to find this binary in `%s`. '. 236 - 'You need to configure %s and include %s.', 237 - 'environment.append-paths', 238 - $this->getEnvConfigLink(), 239 - $path))); 240 - } 241 - } 242 - } 243 - } 244 - 245 - $doc_href = PhabricatorEnv::getDoclink('Managing Daemons with phd'); 246 - 247 - $daemon_instructions = pht( 248 - 'Use %s to start daemons. See %s.', 249 - phutil_tag('tt', array(), 'bin/phd start'), 250 - phutil_tag( 251 - 'a', 252 - array( 253 - 'href' => $doc_href, 254 - ), 255 - pht('Managing Daemons with phd'))); 256 - 257 - 258 - $pull_daemon = id(new PhabricatorDaemonLogQuery()) 259 - ->setViewer(PhabricatorUser::getOmnipotentUser()) 260 - ->withStatus(PhabricatorDaemonLogQuery::STATUS_ALIVE) 261 - ->withDaemonClasses(array('PhabricatorRepositoryPullLocalDaemon')) 262 - ->setLimit(1) 263 - ->execute(); 264 - 265 - if ($pull_daemon) { 266 - 267 - // TODO: In a cluster environment, we need a daemon on this repository's 268 - // host, specifically, and we aren't checking for that right now. This 269 - // is a reasonable proxy for things being more-or-less correctly set up, 270 - // though. 271 - 272 - $view->addItem( 273 - id(new PHUIStatusItemView()) 274 - ->setIcon(PHUIStatusItemView::ICON_ACCEPT, 'green') 275 - ->setTarget(pht('Pull Daemon Running'))); 276 - } else { 277 - $view->addItem( 278 - id(new PHUIStatusItemView()) 279 - ->setIcon(PHUIStatusItemView::ICON_WARNING, 'red') 280 - ->setTarget(pht('Pull Daemon Not Running')) 281 - ->setNote($daemon_instructions)); 282 - } 283 - 284 - 285 - $task_daemon = id(new PhabricatorDaemonLogQuery()) 286 - ->setViewer(PhabricatorUser::getOmnipotentUser()) 287 - ->withStatus(PhabricatorDaemonLogQuery::STATUS_ALIVE) 288 - ->withDaemonClasses(array('PhabricatorTaskmasterDaemon')) 289 - ->setLimit(1) 290 - ->execute(); 291 - if ($task_daemon) { 292 - $view->addItem( 293 - id(new PHUIStatusItemView()) 294 - ->setIcon(PHUIStatusItemView::ICON_ACCEPT, 'green') 295 - ->setTarget(pht('Task Daemon Running'))); 296 - } else { 297 - $view->addItem( 298 - id(new PHUIStatusItemView()) 299 - ->setIcon(PHUIStatusItemView::ICON_WARNING, 'red') 300 - ->setTarget(pht('Task Daemon Not Running')) 301 - ->setNote($daemon_instructions)); 302 - } 303 - 304 - 305 - if ($is_cluster) { 306 - // Just omit this status check for now in cluster environments. We 307 - // could make a service call and pull it from the repository host 308 - // eventually. 309 - } else if ($repository->usesLocalWorkingCopy()) { 310 - $local_parent = dirname($repository->getLocalPath()); 311 - if (Filesystem::pathExists($local_parent)) { 312 - $view->addItem( 313 - id(new PHUIStatusItemView()) 314 - ->setIcon(PHUIStatusItemView::ICON_ACCEPT, 'green') 315 - ->setTarget(pht('Storage Directory OK')) 316 - ->setNote(phutil_tag('tt', array(), $local_parent))); 317 - } else { 318 - $view->addItem( 319 - id(new PHUIStatusItemView()) 320 - ->setIcon(PHUIStatusItemView::ICON_WARNING, 'red') 321 - ->setTarget(pht('No Storage Directory')) 322 - ->setNote( 323 - pht( 324 - 'Storage directory %s does not exist, or is not readable by '. 325 - 'the webserver. Create this directory or make it readable.', 326 - phutil_tag('tt', array(), $local_parent)))); 327 - return $view; 328 - } 329 - 330 - $local_path = $repository->getLocalPath(); 331 - $message = idx($messages, PhabricatorRepositoryStatusMessage::TYPE_INIT); 332 - if ($message) { 333 - switch ($message->getStatusCode()) { 334 - case PhabricatorRepositoryStatusMessage::CODE_ERROR: 335 - $view->addItem( 336 - id(new PHUIStatusItemView()) 337 - ->setIcon(PHUIStatusItemView::ICON_WARNING, 'red') 338 - ->setTarget(pht('Initialization Error')) 339 - ->setNote($message->getParameter('message'))); 340 - return $view; 341 - case PhabricatorRepositoryStatusMessage::CODE_OKAY: 342 - if (Filesystem::pathExists($local_path)) { 343 - $view->addItem( 344 - id(new PHUIStatusItemView()) 345 - ->setIcon(PHUIStatusItemView::ICON_ACCEPT, 'green') 346 - ->setTarget(pht('Working Copy OK')) 347 - ->setNote(phutil_tag('tt', array(), $local_path))); 348 - } else { 349 - $view->addItem( 350 - id(new PHUIStatusItemView()) 351 - ->setIcon(PHUIStatusItemView::ICON_WARNING, 'red') 352 - ->setTarget(pht('Working Copy Error')) 353 - ->setNote( 354 - pht( 355 - 'Working copy %s has been deleted, or is not '. 356 - 'readable by the webserver. Make this directory '. 357 - 'readable. If it has been deleted, the daemons should '. 358 - 'restore it automatically.', 359 - phutil_tag('tt', array(), $local_path)))); 360 - return $view; 361 - } 362 - break; 363 - default: 364 - $view->addItem( 365 - id(new PHUIStatusItemView()) 366 - ->setIcon(PHUIStatusItemView::ICON_CLOCK, 'green') 367 - ->setTarget(pht('Initializing Working Copy')) 368 - ->setNote(pht('Daemons are initializing the working copy.'))); 369 - return $view; 370 - } 371 - } else { 372 - $view->addItem( 373 - id(new PHUIStatusItemView()) 374 - ->setIcon(PHUIStatusItemView::ICON_CLOCK, 'orange') 375 - ->setTarget(pht('No Working Copy Yet')) 376 - ->setNote( 377 - pht('Waiting for daemons to build a working copy.'))); 378 - return $view; 379 - } 380 - } 381 - 382 - $message = idx($messages, PhabricatorRepositoryStatusMessage::TYPE_FETCH); 383 - if ($message) { 384 - switch ($message->getStatusCode()) { 385 - case PhabricatorRepositoryStatusMessage::CODE_ERROR: 386 - $message = $message->getParameter('message'); 387 - 388 - $suggestion = null; 389 - if (preg_match('/Permission denied \(publickey\)./', $message)) { 390 - $suggestion = pht( 391 - 'Public Key Error: This error usually indicates that the '. 392 - 'keypair you have configured does not have permission to '. 393 - 'access the repository.'); 394 - } 395 - 396 - $view->addItem( 397 - id(new PHUIStatusItemView()) 398 - ->setIcon(PHUIStatusItemView::ICON_WARNING, 'red') 399 - ->setTarget(pht('Update Error')) 400 - ->setNote($suggestion)); 401 - return $view; 402 - case PhabricatorRepositoryStatusMessage::CODE_OKAY: 403 - $ago = (PhabricatorTime::getNow() - $message->getEpoch()); 404 - $view->addItem( 405 - id(new PHUIStatusItemView()) 406 - ->setIcon(PHUIStatusItemView::ICON_ACCEPT, 'green') 407 - ->setTarget(pht('Updates OK')) 408 - ->setNote( 409 - pht( 410 - 'Last updated %s (%s ago).', 411 - phabricator_datetime($message->getEpoch(), $viewer), 412 - phutil_format_relative_time_detailed($ago)))); 413 - break; 414 - } 415 - } else { 416 - $view->addItem( 417 - id(new PHUIStatusItemView()) 418 - ->setIcon(PHUIStatusItemView::ICON_CLOCK, 'orange') 419 - ->setTarget(pht('Waiting For Update')) 420 - ->setNote( 421 - pht('Waiting for daemons to read updates.'))); 422 - } 423 - 424 - if ($repository->isImporting()) { 425 - $ratio = $repository->loadImportProgress(); 426 - $percentage = sprintf('%.2f%%', 100 * $ratio); 427 - 428 - $view->addItem( 429 - id(new PHUIStatusItemView()) 430 - ->setIcon(PHUIStatusItemView::ICON_CLOCK, 'green') 431 - ->setTarget(pht('Importing')) 432 - ->setNote( 433 - pht('%s Complete', $percentage))); 434 - } else { 435 - $view->addItem( 436 - id(new PHUIStatusItemView()) 437 - ->setIcon(PHUIStatusItemView::ICON_ACCEPT, 'green') 438 - ->setTarget(pht('Fully Imported'))); 439 - } 440 - 441 - if (idx($messages, PhabricatorRepositoryStatusMessage::TYPE_NEEDS_UPDATE)) { 442 - $view->addItem( 443 - id(new PHUIStatusItemView()) 444 - ->setIcon(PHUIStatusItemView::ICON_UP, 'indigo') 445 - ->setTarget(pht('Prioritized')) 446 - ->setNote(pht('This repository will be updated soon!'))); 447 - } 448 - 449 - return $view; 450 - } 451 - 452 - private function buildRepositoryRawError( 453 - PhabricatorRepository $repository, 454 - array $messages) { 455 - $viewer = $this->getViewer(); 456 - 457 - $can_edit = PhabricatorPolicyFilter::hasCapability( 458 - $viewer, 459 - $repository, 460 - PhabricatorPolicyCapability::CAN_EDIT); 461 - 462 - $raw_error = null; 463 - 464 - $message = idx($messages, PhabricatorRepositoryStatusMessage::TYPE_FETCH); 465 - if ($message) { 466 - switch ($message->getStatusCode()) { 467 - case PhabricatorRepositoryStatusMessage::CODE_ERROR: 468 - $raw_error = $message->getParameter('message'); 469 - break; 470 - } 471 - } 472 - 473 - if ($raw_error !== null) { 474 - if (!$can_edit) { 475 - $raw_message = pht( 476 - 'You must be able to edit a repository to see raw error messages '. 477 - 'because they sometimes disclose sensitive information.'); 478 - $raw_message = phutil_tag('em', array(), $raw_message); 479 - } else { 480 - $raw_message = phutil_escape_html_newlines($raw_error); 481 - } 482 - } else { 483 - $raw_message = null; 484 - } 485 - 486 - return $raw_message; 487 - } 488 - 489 - private function loadStatusMessages(PhabricatorRepository $repository) { 490 - $messages = id(new PhabricatorRepositoryStatusMessage()) 491 - ->loadAllWhere('repositoryID = %d', $repository->getID()); 492 - $messages = mpull($messages, null, 'getStatusType'); 493 - 494 - return $messages; 495 - } 496 - 497 - private function getEnvConfigLink() { 498 - $config_href = '/config/edit/environment.append-paths/'; 499 - return phutil_tag( 500 - 'a', 501 - array( 502 - 'href' => $config_href, 503 - ), 504 - 'environment.append-paths'); 505 - } 506 - 507 - }
+11 -31
src/applications/diffusion/management/DiffusionRepositoryStorageManagementPanel.php
··· 14 14 } 15 15 16 16 public function getManagementPanelIcon() { 17 - $repository = $this->getRepository(); 18 - 19 - if ($repository->getAlmanacServicePHID()) { 20 - return 'fa-sitemap'; 21 - } else if ($repository->isHosted()) { 22 - return 'fa-folder'; 23 - } else { 24 - return 'fa-download'; 25 - } 26 - } 27 - 28 - public function buildManagementPanelCurtain() { 29 - $repository = $this->getRepository(); 30 - $viewer = $this->getViewer(); 31 - $action_list = $this->getNewActionList(); 32 - 33 - $doc_href = PhabricatorEnv::getDoclink('Cluster: Repositories'); 34 - 35 - $action_list->addAction( 36 - id(new PhabricatorActionView()) 37 - ->setIcon('fa-book') 38 - ->setHref($doc_href) 39 - ->setName(pht('Cluster Documentation'))); 40 - 41 - return $this->getNewCurtainView($action_list); 17 + return 'fa-database'; 42 18 } 43 19 44 20 public function buildManagementPanelContent() { ··· 71 47 $view->addProperty(pht('Storage Path'), $storage_path); 72 48 $view->addProperty(pht('Storage Cluster'), $storage_service); 73 49 74 - $box = $this->newBox(pht('Storage'), null); 75 - $box->addPropertyList($view); 76 - return $box; 50 + $doc_href = PhabricatorEnv::getDoclink('Cluster: Repositories'); 51 + 52 + $button = id(new PHUIButtonView()) 53 + ->setTag('a') 54 + ->setIcon('fa-book') 55 + ->setHref($doc_href) 56 + ->setText(pht('Help')); 57 + 58 + return $this->newBox(pht('Storage'), $view, array($button)); 77 59 } 78 60 79 61 private function buildClusterStatusPanel() { ··· 243 225 'date', 244 226 )); 245 227 246 - $box = $this->newBox(pht('Cluster Status'), null); 247 - $box->setTable($table); 248 - return $box; 228 + return $this->newBox(pht('Cluster Status'), $table); 249 229 } 250 230 251 231 }
+16 -33
src/applications/diffusion/management/DiffusionRepositorySubversionManagementPanel.php
··· 19 19 } 20 20 21 21 public function getManagementPanelIcon() { 22 - $repository = $this->getRepository(); 23 - 24 - $has_any = (bool)$repository->getDetail('svn-subpath'); 25 - 26 - if ($has_any) { 27 - return 'fa-database'; 28 - } else { 29 - return 'fa-database grey'; 30 - } 22 + return 'fa-folder'; 31 23 } 32 24 33 25 protected function getEditEngineFieldKeys() { ··· 36 28 ); 37 29 } 38 30 39 - public function buildManagementPanelCurtain() { 40 - $repository = $this->getRepository(); 41 - $viewer = $this->getViewer(); 42 - $action_list = $this->getNewActionList(); 43 - 44 - $can_edit = PhabricatorPolicyFilter::hasCapability( 45 - $viewer, 46 - $repository, 47 - PhabricatorPolicyCapability::CAN_EDIT); 48 - 49 - $subversion_uri = $this->getEditPageURI(); 50 - 51 - $action_list->addAction( 52 - id(new PhabricatorActionView()) 53 - ->setIcon('fa-pencil') 54 - ->setName(pht('Edit Properties')) 55 - ->setHref($subversion_uri) 56 - ->setDisabled(!$can_edit) 57 - ->setWorkflow(!$can_edit)); 58 - 59 - return $this->getNewCurtainView($action_list); 60 - } 61 - 62 31 public function buildManagementPanelContent() { 63 32 $repository = $this->getRepository(); 64 33 $viewer = $this->getViewer(); ··· 71 40 phutil_tag('em', array(), pht('Import Entire Repository'))); 72 41 $view->addProperty(pht('Import Only'), $default_branch); 73 42 43 + $can_edit = PhabricatorPolicyFilter::hasCapability( 44 + $viewer, 45 + $repository, 46 + PhabricatorPolicyCapability::CAN_EDIT); 74 47 75 - return $this->newBox(pht('Subversion'), $view); 48 + $subversion_uri = $this->getEditPageURI(); 49 + 50 + $button = id(new PHUIButtonView()) 51 + ->setTag('a') 52 + ->setIcon('fa-pencil') 53 + ->setText(pht('Edit')) 54 + ->setHref($subversion_uri) 55 + ->setDisabled(!$can_edit) 56 + ->setWorkflow(!$can_edit); 57 + 58 + return $this->newBox(pht('Subversion'), $view, array($button)); 76 59 } 77 60 78 61 }
+17 -35
src/applications/diffusion/management/DiffusionRepositorySymbolsManagementPanel.php
··· 14 14 } 15 15 16 16 public function getManagementPanelIcon() { 17 - $repository = $this->getRepository(); 18 - 19 - $has_any = 20 - $repository->getSymbolLanguages() || 21 - $repository->getSymbolSources(); 22 - 23 - if ($has_any) { 24 - return 'fa-link'; 25 - } else { 26 - return 'fa-link grey'; 27 - } 17 + return 'fa-bullseye'; 28 18 } 29 19 30 20 protected function getEditEngineFieldKeys() { ··· 34 24 ); 35 25 } 36 26 37 - public function buildManagementPanelCurtain() { 38 - $repository = $this->getRepository(); 39 - $viewer = $this->getViewer(); 40 - $action_list = $this->getNewActionList(); 41 - 42 - $can_edit = PhabricatorPolicyFilter::hasCapability( 43 - $viewer, 44 - $repository, 45 - PhabricatorPolicyCapability::CAN_EDIT); 46 - 47 - $symbols_uri = $this->getEditPageURI(); 48 - 49 - $action_list->addAction( 50 - id(new PhabricatorActionView()) 51 - ->setIcon('fa-pencil') 52 - ->setName(pht('Edit Symbols')) 53 - ->setHref($symbols_uri) 54 - ->setDisabled(!$can_edit) 55 - ->setWorkflow(!$can_edit)); 56 - 57 - return $this->getNewCurtainView($action_list); 58 - } 59 - 60 27 public function buildManagementPanelContent() { 61 28 $repository = $this->getRepository(); 62 29 $viewer = $this->getViewer(); ··· 80 47 } 81 48 $view->addProperty(pht('Uses Symbols From'), $sources); 82 49 83 - return $this->newBox(pht('Symbols'), $view); 50 + $can_edit = PhabricatorPolicyFilter::hasCapability( 51 + $viewer, 52 + $repository, 53 + PhabricatorPolicyCapability::CAN_EDIT); 54 + 55 + $symbols_uri = $this->getEditPageURI(); 56 + 57 + $button = id(new PHUIButtonView()) 58 + ->setTag('a') 59 + ->setIcon('fa-pencil') 60 + ->setText(pht('Edit')) 61 + ->setHref($symbols_uri) 62 + ->setDisabled(!$can_edit) 63 + ->setWorkflow(!$can_edit); 64 + 65 + return $this->newBox(pht('Symbols'), $view, array($button)); 84 66 } 85 67 86 68 }
+24 -33
src/applications/diffusion/management/DiffusionRepositoryURIsManagementPanel.php
··· 10 10 } 11 11 12 12 public function getManagementPanelIcon() { 13 - return 'fa-cogs'; 13 + return 'fa-globe'; 14 14 } 15 15 16 16 public function getManagementPanelOrder() { 17 17 return 400; 18 - } 19 - 20 - public function buildManagementPanelCurtain() { 21 - $repository = $this->getRepository(); 22 - $viewer = $this->getViewer(); 23 - $action_list = $this->getNewActionList(); 24 - 25 - $can_edit = PhabricatorPolicyFilter::hasCapability( 26 - $viewer, 27 - $repository, 28 - PhabricatorPolicyCapability::CAN_EDIT); 29 - 30 - $doc_href = PhabricatorEnv::getDoclink('Diffusion User Guide: URIs'); 31 - $add_href = $repository->getPathURI('uri/edit/'); 32 - 33 - $action_list->addAction( 34 - id(new PhabricatorActionView()) 35 - ->setIcon('fa-plus') 36 - ->setHref($add_href) 37 - ->setDisabled(!$can_edit) 38 - ->setName(pht('Add New URI'))); 39 - 40 - $action_list->addAction( 41 - id(new PhabricatorActionView()) 42 - ->setIcon('fa-book') 43 - ->setHref($doc_href) 44 - ->setName(pht('URI Documentation'))); 45 - 46 - return $this->getNewCurtainView($action_list); 47 18 } 48 19 49 20 public function buildManagementPanelContent() { ··· 151 122 ->setSeverity(PHUIInfoView::SEVERITY_NOTICE) 152 123 ->setErrors($messages); 153 124 154 - $box = $this->newBox(pht('Repository URIs'), null); 155 - $box->setTable($table); 125 + $can_edit = PhabricatorPolicyFilter::hasCapability( 126 + $viewer, 127 + $repository, 128 + PhabricatorPolicyCapability::CAN_EDIT); 129 + 130 + $doc_href = PhabricatorEnv::getDoclink('Diffusion User Guide: URIs'); 131 + $add_href = $repository->getPathURI('uri/edit/'); 156 132 157 - return array($info_view, $box); 133 + $add = id(new PHUIButtonView()) 134 + ->setTag('a') 135 + ->setIcon('fa-plus') 136 + ->setHref($add_href) 137 + ->setDisabled(!$can_edit) 138 + ->setText(pht('New URI')); 139 + 140 + $help = id(new PHUIButtonView()) 141 + ->setTag('a') 142 + ->setIcon('fa-book') 143 + ->setHref($doc_href) 144 + ->setText(pht('Help')); 145 + 146 + $box = $this->newBox(pht('Repository URIs'), $table, array($add, $help)); 147 + 148 + return array($box, $info_view); 158 149 } 159 150 160 151 }
+5
webroot/rsrc/css/phui/phui-box.css
··· 136 136 .phui-box-white-config .phui-header-header { 137 137 color: {$bluetext}; 138 138 } 139 + 140 + .phui-box-white-config .phui-header-action-links .button { 141 + margin-top: 0; 142 + margin-bottom: 0; 143 + }
+4
webroot/rsrc/css/phui/phui-header-view.css
··· 337 337 color: {$blacktext}; 338 338 } 339 339 340 + .phui-profile-header.phui-header-shell .phui-header-header a { 341 + color: {$blacktext}; 342 + } 343 + 340 344 .phui-profile-header .phui-header-col3 { 341 345 vertical-align: top; 342 346 }