1
0
Fork 0
mirror of https://we.phorge.it/source/phorge.git synced 2024-11-26 08:42:41 +01:00

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
This commit is contained in:
Chad Little 2017-09-05 19:01:18 -07:00
parent f40f3ca74c
commit e1fd74ddb5
21 changed files with 749 additions and 978 deletions

View file

@ -9,7 +9,7 @@ return array(
'names' => array( 'names' => array(
'conpherence.pkg.css' => 'e68cf1fa', 'conpherence.pkg.css' => 'e68cf1fa',
'conpherence.pkg.js' => 'b5b51108', 'conpherence.pkg.js' => 'b5b51108',
'core.pkg.css' => '042e1782', 'core.pkg.css' => 'ebbf04f7',
'core.pkg.js' => '6c085267', 'core.pkg.js' => '6c085267',
'darkconsole.pkg.js' => '1f9a31bc', 'darkconsole.pkg.js' => '1f9a31bc',
'differential.pkg.css' => '45951e9e', 'differential.pkg.css' => '45951e9e',
@ -142,7 +142,7 @@ return array(
'rsrc/css/phui/phui-badge.css' => '22c0cf4f', 'rsrc/css/phui/phui-badge.css' => '22c0cf4f',
'rsrc/css/phui/phui-basic-nav-view.css' => '98c11ab3', 'rsrc/css/phui/phui-basic-nav-view.css' => '98c11ab3',
'rsrc/css/phui/phui-big-info-view.css' => 'acc3492c', 'rsrc/css/phui/phui-big-info-view.css' => 'acc3492c',
'rsrc/css/phui/phui-box.css' => '4165eb0d', 'rsrc/css/phui/phui-box.css' => '9f3745fb',
'rsrc/css/phui/phui-chart.css' => '6bf6f78e', 'rsrc/css/phui/phui-chart.css' => '6bf6f78e',
'rsrc/css/phui/phui-cms.css' => '504b4b23', 'rsrc/css/phui/phui-cms.css' => '504b4b23',
'rsrc/css/phui/phui-comment-form.css' => 'ac68149f', 'rsrc/css/phui/phui-comment-form.css' => 'ac68149f',
@ -157,7 +157,7 @@ return array(
'rsrc/css/phui/phui-form-view.css' => 'ae9f8d16', 'rsrc/css/phui/phui-form-view.css' => 'ae9f8d16',
'rsrc/css/phui/phui-form.css' => '7aaa04e3', 'rsrc/css/phui/phui-form.css' => '7aaa04e3',
'rsrc/css/phui/phui-head-thing.css' => 'fd311e5f', 'rsrc/css/phui/phui-head-thing.css' => 'fd311e5f',
'rsrc/css/phui/phui-header-view.css' => '3c722648', 'rsrc/css/phui/phui-header-view.css' => '369275d6',
'rsrc/css/phui/phui-hovercard.css' => 'f0592bcf', 'rsrc/css/phui/phui-hovercard.css' => 'f0592bcf',
'rsrc/css/phui/phui-icon-set-selector.css' => '87db8fee', 'rsrc/css/phui/phui-icon-set-selector.css' => '87db8fee',
'rsrc/css/phui/phui-icon.css' => '5c4a5de6', 'rsrc/css/phui/phui-icon.css' => '5c4a5de6',
@ -820,7 +820,7 @@ return array(
'phui-badge-view-css' => '22c0cf4f', 'phui-badge-view-css' => '22c0cf4f',
'phui-basic-nav-view-css' => '98c11ab3', 'phui-basic-nav-view-css' => '98c11ab3',
'phui-big-info-view-css' => 'acc3492c', 'phui-big-info-view-css' => 'acc3492c',
'phui-box-css' => '4165eb0d', 'phui-box-css' => '9f3745fb',
'phui-button-bar-css' => 'f1ff5494', 'phui-button-bar-css' => 'f1ff5494',
'phui-button-css' => '1863cc6e', 'phui-button-css' => '1863cc6e',
'phui-button-simple-css' => '8e1baf68', 'phui-button-simple-css' => '8e1baf68',
@ -843,7 +843,7 @@ return array(
'phui-form-css' => '7aaa04e3', 'phui-form-css' => '7aaa04e3',
'phui-form-view-css' => 'ae9f8d16', 'phui-form-view-css' => 'ae9f8d16',
'phui-head-thing-view-css' => 'fd311e5f', 'phui-head-thing-view-css' => 'fd311e5f',
'phui-header-view-css' => '3c722648', 'phui-header-view-css' => '369275d6',
'phui-hovercard' => '1bd28176', 'phui-hovercard' => '1bd28176',
'phui-hovercard-view-css' => 'f0592bcf', 'phui-hovercard-view-css' => 'f0592bcf',
'phui-icon-set-selector-css' => '87db8fee', 'phui-icon-set-selector-css' => '87db8fee',

View file

@ -843,7 +843,6 @@ phutil_register_library_map(array(
'DiffusionRepositoryController' => 'applications/diffusion/controller/DiffusionRepositoryController.php', 'DiffusionRepositoryController' => 'applications/diffusion/controller/DiffusionRepositoryController.php',
'DiffusionRepositoryDatasource' => 'applications/diffusion/typeahead/DiffusionRepositoryDatasource.php', 'DiffusionRepositoryDatasource' => 'applications/diffusion/typeahead/DiffusionRepositoryDatasource.php',
'DiffusionRepositoryDefaultController' => 'applications/diffusion/controller/DiffusionRepositoryDefaultController.php', 'DiffusionRepositoryDefaultController' => 'applications/diffusion/controller/DiffusionRepositoryDefaultController.php',
'DiffusionRepositoryDocumentationManagementPanel' => 'applications/diffusion/management/DiffusionRepositoryDocumentationManagementPanel.php',
'DiffusionRepositoryEditActivateController' => 'applications/diffusion/controller/DiffusionRepositoryEditActivateController.php', 'DiffusionRepositoryEditActivateController' => 'applications/diffusion/controller/DiffusionRepositoryEditActivateController.php',
'DiffusionRepositoryEditConduitAPIMethod' => 'applications/diffusion/conduit/DiffusionRepositoryEditConduitAPIMethod.php', 'DiffusionRepositoryEditConduitAPIMethod' => 'applications/diffusion/conduit/DiffusionRepositoryEditConduitAPIMethod.php',
'DiffusionRepositoryEditController' => 'applications/diffusion/controller/DiffusionRepositoryEditController.php', 'DiffusionRepositoryEditController' => 'applications/diffusion/controller/DiffusionRepositoryEditController.php',
@ -864,7 +863,6 @@ phutil_register_library_map(array(
'DiffusionRepositoryRemarkupRule' => 'applications/diffusion/remarkup/DiffusionRepositoryRemarkupRule.php', 'DiffusionRepositoryRemarkupRule' => 'applications/diffusion/remarkup/DiffusionRepositoryRemarkupRule.php',
'DiffusionRepositorySearchConduitAPIMethod' => 'applications/diffusion/conduit/DiffusionRepositorySearchConduitAPIMethod.php', 'DiffusionRepositorySearchConduitAPIMethod' => 'applications/diffusion/conduit/DiffusionRepositorySearchConduitAPIMethod.php',
'DiffusionRepositoryStagingManagementPanel' => 'applications/diffusion/management/DiffusionRepositoryStagingManagementPanel.php', 'DiffusionRepositoryStagingManagementPanel' => 'applications/diffusion/management/DiffusionRepositoryStagingManagementPanel.php',
'DiffusionRepositoryStatusManagementPanel' => 'applications/diffusion/management/DiffusionRepositoryStatusManagementPanel.php',
'DiffusionRepositoryStorageManagementPanel' => 'applications/diffusion/management/DiffusionRepositoryStorageManagementPanel.php', 'DiffusionRepositoryStorageManagementPanel' => 'applications/diffusion/management/DiffusionRepositoryStorageManagementPanel.php',
'DiffusionRepositorySubversionManagementPanel' => 'applications/diffusion/management/DiffusionRepositorySubversionManagementPanel.php', 'DiffusionRepositorySubversionManagementPanel' => 'applications/diffusion/management/DiffusionRepositorySubversionManagementPanel.php',
'DiffusionRepositorySymbolsManagementPanel' => 'applications/diffusion/management/DiffusionRepositorySymbolsManagementPanel.php', 'DiffusionRepositorySymbolsManagementPanel' => 'applications/diffusion/management/DiffusionRepositorySymbolsManagementPanel.php',
@ -5863,7 +5861,6 @@ phutil_register_library_map(array(
'DiffusionRepositoryController' => 'DiffusionController', 'DiffusionRepositoryController' => 'DiffusionController',
'DiffusionRepositoryDatasource' => 'PhabricatorTypeaheadDatasource', 'DiffusionRepositoryDatasource' => 'PhabricatorTypeaheadDatasource',
'DiffusionRepositoryDefaultController' => 'DiffusionController', 'DiffusionRepositoryDefaultController' => 'DiffusionController',
'DiffusionRepositoryDocumentationManagementPanel' => 'DiffusionRepositoryManagementPanel',
'DiffusionRepositoryEditActivateController' => 'DiffusionRepositoryManageController', 'DiffusionRepositoryEditActivateController' => 'DiffusionRepositoryManageController',
'DiffusionRepositoryEditConduitAPIMethod' => 'PhabricatorEditEngineAPIMethod', 'DiffusionRepositoryEditConduitAPIMethod' => 'PhabricatorEditEngineAPIMethod',
'DiffusionRepositoryEditController' => 'DiffusionRepositoryManageController', 'DiffusionRepositoryEditController' => 'DiffusionRepositoryManageController',
@ -5884,7 +5881,6 @@ phutil_register_library_map(array(
'DiffusionRepositoryRemarkupRule' => 'PhabricatorObjectRemarkupRule', 'DiffusionRepositoryRemarkupRule' => 'PhabricatorObjectRemarkupRule',
'DiffusionRepositorySearchConduitAPIMethod' => 'PhabricatorSearchEngineAPIMethod', 'DiffusionRepositorySearchConduitAPIMethod' => 'PhabricatorSearchEngineAPIMethod',
'DiffusionRepositoryStagingManagementPanel' => 'DiffusionRepositoryManagementPanel', 'DiffusionRepositoryStagingManagementPanel' => 'DiffusionRepositoryManagementPanel',
'DiffusionRepositoryStatusManagementPanel' => 'DiffusionRepositoryManagementPanel',
'DiffusionRepositoryStorageManagementPanel' => 'DiffusionRepositoryManagementPanel', 'DiffusionRepositoryStorageManagementPanel' => 'DiffusionRepositoryManagementPanel',
'DiffusionRepositorySubversionManagementPanel' => 'DiffusionRepositoryManagementPanel', 'DiffusionRepositorySubversionManagementPanel' => 'DiffusionRepositoryManagementPanel',
'DiffusionRepositorySymbolsManagementPanel' => 'DiffusionRepositoryManagementPanel', 'DiffusionRepositorySymbolsManagementPanel' => 'DiffusionRepositoryManagementPanel',

View file

@ -13,7 +13,7 @@ final class DiffusionRepositoryEditUpdateController
$drequest = $this->getDiffusionRequest(); $drequest = $this->getDiffusionRequest();
$repository = $drequest->getRepository(); $repository = $drequest->getRepository();
$panel_uri = id(new DiffusionRepositoryStatusManagementPanel()) $panel_uri = id(new DiffusionRepositoryBasicsManagementPanel())
->setRepository($repository) ->setRepository($repository)
->getPanelURI(); ->getPanelURI();

View file

@ -22,4 +22,20 @@ abstract class DiffusionRepositoryManageController
return $crumbs; return $crumbs;
} }
public function newBox($title, $content, $action = null) {
$header = id(new PHUIHeaderView())
->setHeader($title);
if ($action) {
$header->addActionItem($action);
}
$view = id(new PHUIObjectBoxView())
->setHeader($header)
->appendChild($content)
->setBackground(PHUIObjectBoxView::WHITE_CONFIG);
return $view;
}
} }

View file

@ -53,6 +53,10 @@ final class DiffusionRepositoryManagePanelsController
$panel = $panels[$selected]; $panel = $panels[$selected];
$crumbs = $this->buildApplicationCrumbs();
$crumbs->addTextCrumb($panel->getManagementPanelLabel());
$crumbs->setBorder(true);
$content = $panel->buildManagementPanelContent(); $content = $panel->buildManagementPanelContent();
$title = array( $title = array(
@ -60,45 +64,17 @@ final class DiffusionRepositoryManagePanelsController
$repository->getDisplayName(), $repository->getDisplayName(),
); );
$crumbs = $this->buildApplicationCrumbs(); $header = $this->buildHeaderView($repository->getDisplayName());
$crumbs->addTextCrumb($panel->getManagementPanelLabel());
$crumbs->setBorder(true);
$header_text = pht(
'%s: %s',
$repository->getDisplayName(),
$panel->getManagementPanelLabel());
$header = id(new PHUIHeaderView())
->setHeader($header_text)
->setHeaderIcon('fa-pencil');
if ($repository->isTracked()) {
$header->setStatus('fa-check', 'bluegrey', pht('Active'));
} else {
$header->setStatus('fa-ban', 'dark', pht('Inactive'));
}
$header->addActionLink(
id(new PHUIButtonView())
->setTag('a')
->setText(pht('View Repository'))
->setHref($repository->getURI())
->setIcon('fa-code')
->setColor(PHUIButtonView::GREEN));
$view = id(new PHUITwoColumnView()) $view = id(new PHUITwoColumnView())
->setHeader($header) ->setHeader($header)
->setNavigation($nav)
->setFixed(true)
->setMainColumn($content); ->setMainColumn($content);
$curtain = $panel->buildManagementPanelCurtain();
if ($curtain) {
$view->setCurtain($curtain);
}
return $this->newPage() return $this->newPage()
->setTitle($title) ->setTitle($title)
->setCrumbs($crumbs) ->setCrumbs($crumbs)
->setNavigation($nav)
->appendChild($view); ->appendChild($view);
} }
@ -113,12 +89,6 @@ final class DiffusionRepositoryManagePanelsController
$nav = id(new AphrontSideNavFilterView()) $nav = id(new AphrontSideNavFilterView())
->setBaseURI($base_uri); ->setBaseURI($base_uri);
$item = id(new PHUIListItemView())
->setName(pht('manage'))
->setType(PHUIListItemView::TYPE_LABEL);
$nav->addMenuItem($item);
foreach ($panels as $panel) { foreach ($panels as $panel) {
$key = $panel->getManagementPanelKey(); $key = $panel->getManagementPanelKey();
$label = $panel->getManagementPanelLabel(); $label = $panel->getManagementPanelLabel();
@ -140,6 +110,46 @@ final class DiffusionRepositoryManagePanelsController
return $nav; return $nav;
} }
public function buildHeaderView($title) {
$viewer = $this->getViewer();
$drequest = $this->getDiffusionRequest();
$repository = $drequest->getRepository();
$header = id(new PHUIHeaderView())
->setHeader($title)
->setProfileHeader(true)
->setHref($repository->getURI())
->setImage($repository->getProfileImageURI());
if ($repository->isTracked()) {
$header->setStatus('fa-check', 'bluegrey', pht('Active'));
} else {
$header->setStatus('fa-ban', 'dark', pht('Inactive'));
}
$doc_href = PhabricatorEnv::getDoclink(
'Diffusion User Guide: Managing Repositories');
$header->addActionLink(
id(new PHUIButtonView())
->setTag('a')
->setText(pht('View Repository'))
->setHref($repository->getURI())
->setIcon('fa-code')
->setColor(PHUIButtonView::GREY));
$header->addActionLink(
id(new PHUIButtonView())
->setTag('a')
->setIcon('fa-book')
->setHref($doc_href)
->setText(pht('Help'))
->setColor(PHUIButtonView::GREY));
return $header;
}
public function newTimeline(PhabricatorRepository $repository) { public function newTimeline(PhabricatorRepository $repository) {
$timeline = $this->buildTransactionTimeline( $timeline = $this->buildTransactionTimeline(
$repository, $repository,

View file

@ -14,20 +14,7 @@ final class DiffusionRepositoryActionsManagementPanel
} }
public function getManagementPanelIcon() { public function getManagementPanelIcon() {
$repository = $this->getRepository(); return 'fa-flash';
$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() { protected function getEditEngineFieldKeys() {
@ -37,29 +24,6 @@ final class DiffusionRepositoryActionsManagementPanel
); );
} }
public function buildManagementPanelCurtain() {
$repository = $this->getRepository();
$viewer = $this->getViewer();
$action_list = $this->getNewActionList();
$can_edit = PhabricatorPolicyFilter::hasCapability(
$viewer,
$repository,
PhabricatorPolicyCapability::CAN_EDIT);
$actions_uri = $this->getEditPageURI();
$action_list->addAction(
id(new PhabricatorActionView())
->setIcon('fa-pencil')
->setName(pht('Edit Actions'))
->setHref($actions_uri)
->setDisabled(!$can_edit)
->setWorkflow(!$can_edit));
return $this->getNewCurtainView($action_list);
}
public function buildManagementPanelContent() { public function buildManagementPanelContent() {
$repository = $this->getRepository(); $repository = $this->getRepository();
$viewer = $this->getViewer(); $viewer = $this->getViewer();
@ -79,7 +43,22 @@ final class DiffusionRepositoryActionsManagementPanel
$autoclose = phutil_tag('em', array(), $autoclose); $autoclose = phutil_tag('em', array(), $autoclose);
$view->addProperty(pht('Autoclose'), $autoclose); $view->addProperty(pht('Autoclose'), $autoclose);
return $this->newBox(pht('Actions'), $view); $can_edit = PhabricatorPolicyFilter::hasCapability(
$viewer,
$repository,
PhabricatorPolicyCapability::CAN_EDIT);
$actions_uri = $this->getEditPageURI();
$button = id(new PHUIButtonView())
->setTag('a')
->setIcon('fa-pencil')
->setText(pht('Edit'))
->setHref($actions_uri)
->setDisabled(!$can_edit)
->setWorkflow(!$can_edit);
return $this->newBox(pht('Actions'), $view, array($button));
} }
} }

View file

@ -27,59 +27,18 @@ final class DiffusionRepositoryAutomationManagementPanel
public function getManagementPanelIcon() { public function getManagementPanelIcon() {
$repository = $this->getRepository(); $repository = $this->getRepository();
if (!$repository->canPerformAutomation()) {
return 'fa-truck grey';
}
$blueprint_phids = $repository->getAutomationBlueprintPHIDs(); $blueprint_phids = $repository->getAutomationBlueprintPHIDs();
if (!$blueprint_phids) {
return 'fa-truck grey';
}
$is_authorized = DrydockAuthorizationQuery::isFullyAuthorized( $is_authorized = DrydockAuthorizationQuery::isFullyAuthorized(
$repository->getPHID(), $repository->getPHID(),
$blueprint_phids); $blueprint_phids);
if (!$is_authorized) { if (!$is_authorized) {
return 'fa-exclamation-triangle yellow'; return 'fa-exclamation-triangle';
} }
return 'fa-truck'; return 'fa-truck';
} }
public function buildManagementPanelCurtain() {
$repository = $this->getRepository();
$viewer = $this->getViewer();
$action_list = $this->getNewActionList();
$can_edit = PhabricatorPolicyFilter::hasCapability(
$viewer,
$repository,
PhabricatorPolicyCapability::CAN_EDIT);
$can_test = $can_edit && $repository->canPerformAutomation();
$automation_uri = $this->getEditPageURI();
$test_uri = $repository->getPathURI('edit/testautomation/');
$action_list->addAction(
id(new PhabricatorActionView())
->setIcon('fa-pencil')
->setName(pht('Edit Automation'))
->setHref($automation_uri)
->setDisabled(!$can_edit)
->setWorkflow(!$can_edit));
$action_list->addAction(
id(new PhabricatorActionView())
->setIcon('fa-gamepad')
->setName(pht('Test Configuration'))
->setWorkflow(true)
->setDisabled(!$can_test)
->setHref($test_uri));
return $this->getNewCurtainView($action_list);
}
public function buildManagementPanelContent() { public function buildManagementPanelContent() {
$repository = $this->getRepository(); $repository = $this->getRepository();
$viewer = $this->getViewer(); $viewer = $this->getViewer();
@ -99,7 +58,33 @@ final class DiffusionRepositoryAutomationManagementPanel
$view->addProperty(pht('Automation'), $blueprint_view); $view->addProperty(pht('Automation'), $blueprint_view);
return $this->newBox(pht('Automation'), $view); $can_edit = PhabricatorPolicyFilter::hasCapability(
$viewer,
$repository,
PhabricatorPolicyCapability::CAN_EDIT);
$can_test = $can_edit && $repository->canPerformAutomation();
$automation_uri = $this->getEditPageURI();
$test_uri = $repository->getPathURI('edit/testautomation/');
$edit = id(new PHUIButtonView())
->setTag('a')
->setIcon('fa-pencil')
->setText(pht('Edit'))
->setHref($automation_uri)
->setDisabled(!$can_edit)
->setWorkflow(!$can_edit);
$test = id(new PHUIButtonView())
->setTag('a')
->setIcon('fa-gamepad')
->setText(pht('Test Config'))
->setWorkflow(true)
->setDisabled(!$can_test)
->setHref($test_uri);
return $this->newBox(pht('Automation'), $view, array($edit, $test));
} }
} }

View file

@ -14,13 +14,7 @@ final class DiffusionRepositoryBasicsManagementPanel
} }
public function getManagementPanelIcon() { public function getManagementPanelIcon() {
$repository = $this->getRepository(); return 'fa-code';
if (!$repository->isTracked()) {
return 'fa-ban indigo';
} else {
return 'fa-code';
}
} }
protected function getEditEngineFieldKeys() { protected function getEditEngineFieldKeys() {
@ -33,10 +27,11 @@ final class DiffusionRepositoryBasicsManagementPanel
); );
} }
public function buildManagementPanelCurtain() { private function buildActionMenu() {
$repository = $this->getRepository(); $repository = $this->getRepository();
$viewer = $this->getViewer(); $viewer = $this->getViewer();
$action_list = $this->getNewActionList(); $action_list = id(new PhabricatorActionListView())
->setViewer($viewer);
$can_edit = PhabricatorPolicyFilter::hasCapability( $can_edit = PhabricatorPolicyFilter::hasCapability(
$viewer, $viewer,
@ -50,27 +45,22 @@ final class DiffusionRepositoryBasicsManagementPanel
$dangerous_uri = $repository->getPathURI('edit/dangerous/'); $dangerous_uri = $repository->getPathURI('edit/dangerous/');
if ($repository->isTracked()) { if ($repository->isTracked()) {
$activate_icon = 'fa-pause';
$activate_label = pht('Deactivate Repository'); $activate_label = pht('Deactivate Repository');
} else { } else {
$activate_icon = 'fa-play';
$activate_label = pht('Activate Repository'); $activate_label = pht('Activate Repository');
} }
$should_dangerous = $repository->shouldAllowDangerousChanges(); $should_dangerous = $repository->shouldAllowDangerousChanges();
if ($should_dangerous) { if ($should_dangerous) {
$dangerous_icon = 'fa-shield';
$dangerous_name = pht('Prevent Dangerous Changes'); $dangerous_name = pht('Prevent Dangerous Changes');
$can_dangerous = $can_edit; $can_dangerous = $can_edit;
} else { } else {
$dangerous_icon = 'fa-bullseye';
$dangerous_name = pht('Allow Dangerous Changes'); $dangerous_name = pht('Allow Dangerous Changes');
$can_dangerous = ($can_edit && $repository->canAllowDangerousChanges()); $can_dangerous = ($can_edit && $repository->canAllowDangerousChanges());
} }
$action_list->addAction( $action_list->addAction(
id(new PhabricatorActionView()) id(new PhabricatorActionView())
->setIcon('fa-pencil')
->setName(pht('Edit Basic Information')) ->setName(pht('Edit Basic Information'))
->setHref($edit_uri) ->setHref($edit_uri)
->setDisabled(!$can_edit) ->setDisabled(!$can_edit)
@ -78,7 +68,6 @@ final class DiffusionRepositoryBasicsManagementPanel
$action_list->addAction( $action_list->addAction(
id(new PhabricatorActionView()) id(new PhabricatorActionView())
->setIcon('fa-text-width')
->setName(pht('Edit Text Encoding')) ->setName(pht('Edit Text Encoding'))
->setHref($encoding_uri) ->setHref($encoding_uri)
->setDisabled(!$can_edit) ->setDisabled(!$can_edit)
@ -86,7 +75,6 @@ final class DiffusionRepositoryBasicsManagementPanel
$action_list->addAction( $action_list->addAction(
id(new PhabricatorActionView()) id(new PhabricatorActionView())
->setIcon($dangerous_icon)
->setName($dangerous_name) ->setName($dangerous_name)
->setHref($dangerous_uri) ->setHref($dangerous_uri)
->setDisabled(!$can_dangerous) ->setDisabled(!$can_dangerous)
@ -95,26 +83,37 @@ final class DiffusionRepositoryBasicsManagementPanel
$action_list->addAction( $action_list->addAction(
id(new PhabricatorActionView()) id(new PhabricatorActionView())
->setHref($activate_uri) ->setHref($activate_uri)
->setIcon($activate_icon)
->setName($activate_label) ->setName($activate_label)
->setDisabled(!$can_edit) ->setDisabled(!$can_edit)
->setWorkflow(true)); ->setWorkflow(true));
$action_list->addAction(
id(new PhabricatorActionView())
->setType(PhabricatorActionView::TYPE_DIVIDER));
$action_list->addAction( $action_list->addAction(
id(new PhabricatorActionView()) id(new PhabricatorActionView())
->setName(pht('Delete Repository')) ->setName(pht('Delete Repository'))
->setIcon('fa-times')
->setHref($delete_uri) ->setHref($delete_uri)
->setColor(PhabricatorActionView::RED)
->setDisabled(true) ->setDisabled(true)
->setWorkflow(true)); ->setWorkflow(true));
return $this->getNewCurtainView($action_list); return $action_list;
} }
public function buildManagementPanelContent() { public function buildManagementPanelContent() {
$result = array();
$basics = $this->newBox(pht('Repository Basics'), $this->buildBasics()); $button = id(new PHUIButtonView())
->setTag('a')
->setText(pht('Actions'))
->setHref('#')
->setIcon('fa-bars')
->addClass('phui-mobile-menu')
->setDropdownMenu($this->buildActionMenu());
$basics = $this->buildBasics();
$basics = $this->newBox(pht('Properties'), $basics, array($button));
$repository = $this->getRepository(); $repository = $this->getRepository();
$is_new = $repository->isNewlyInitialized(); $is_new = $repository->isNewlyInitialized();
@ -144,14 +143,13 @@ final class DiffusionRepositoryBasicsManagementPanel
->setErrors($messages); ->setErrors($messages);
} }
$result[] = $basics;
$description = $this->buildDescription(); $description = $this->buildDescription();
if ($description) { if ($description) {
$result[] = $this->newBox(pht('Description'), $description); $description = $this->newBox(pht('Description'), $description);
} }
$status = $this->buildStatus();
return array($info_view, $result); return array($info_view, $basics, $description, $status);
} }
private function buildBasics() { private function buildBasics() {
@ -213,7 +211,7 @@ final class DiffusionRepositoryBasicsManagementPanel
$view = id(new PHUIPropertyListView()) $view = id(new PHUIPropertyListView())
->setViewer($viewer); ->setViewer($viewer);
if (!strlen($description)) { if (!strlen($description)) {
$description = phutil_tag('em', array(), pht('No description provided.')); return null;
} else { } else {
$description = new PHUIRemarkupView($viewer, $description); $description = new PHUIRemarkupView($viewer, $description);
} }
@ -222,4 +220,471 @@ final class DiffusionRepositoryBasicsManagementPanel
return $view; return $view;
} }
private function buildStatus() {
$repository = $this->getRepository();
$viewer = $this->getViewer();
$update_uri = $repository->getPathURI('edit/update/');
$view = id(new PHUIPropertyListView())
->setViewer($viewer);
$view->addProperty(
pht('Update Frequency'),
$this->buildRepositoryUpdateInterval($repository));
$messages = $this->loadStatusMessages($repository);
$status = $this->buildRepositoryStatus($repository, $messages);
$raw_error = $this->buildRepositoryRawError($repository, $messages);
$view->addProperty(pht('Status'), $status);
if ($raw_error) {
$view->addSectionHeader(pht('Raw Error'));
$view->addTextContent($raw_error);
}
$can_edit = PhabricatorPolicyFilter::hasCapability(
$viewer,
$repository,
PhabricatorPolicyCapability::CAN_EDIT);
$button = id(new PHUIButtonView())
->setTag('a')
->setIcon('fa-refresh')
->setText(pht('Update Now'))
->setWorkflow(true)
->setDisabled(!$can_edit)
->setHref($update_uri);
return $this->newBox(pht('Status'), $view, array($button));
}
private function buildRepositoryUpdateInterval(
PhabricatorRepository $repository) {
$smart_wait = $repository->loadUpdateInterval();
$doc_href = PhabricatorEnv::getDoclink(
'Diffusion User Guide: Repository Updates');
return array(
phutil_format_relative_time_detailed($smart_wait),
" \xC2\xB7 ",
phutil_tag(
'a',
array(
'href' => $doc_href,
'target' => '_blank',
),
pht('Learn More')),
);
}
private function buildRepositoryStatus(
PhabricatorRepository $repository,
array $messages) {
$viewer = $this->getViewer();
$is_cluster = $repository->getAlmanacServicePHID();
$view = new PHUIStatusListView();
if ($repository->isTracked()) {
$view->addItem(
id(new PHUIStatusItemView())
->setIcon(PHUIStatusItemView::ICON_ACCEPT, 'green')
->setTarget(pht('Repository Active')));
} else {
$view->addItem(
id(new PHUIStatusItemView())
->setIcon(PHUIStatusItemView::ICON_WARNING, 'bluegrey')
->setTarget(pht('Repository Inactive'))
->setNote(
pht('Activate this repository to begin or resume import.')));
return $view;
}
$binaries = array();
$svnlook_check = false;
switch ($repository->getVersionControlSystem()) {
case PhabricatorRepositoryType::REPOSITORY_TYPE_GIT:
$binaries[] = 'git';
break;
case PhabricatorRepositoryType::REPOSITORY_TYPE_SVN:
$binaries[] = 'svn';
break;
case PhabricatorRepositoryType::REPOSITORY_TYPE_MERCURIAL:
$binaries[] = 'hg';
break;
}
if ($repository->isHosted()) {
$proto_https = PhabricatorRepositoryURI::BUILTIN_PROTOCOL_HTTPS;
$proto_http = PhabricatorRepositoryURI::BUILTIN_PROTOCOL_HTTP;
$can_http = $repository->canServeProtocol($proto_http, false) ||
$repository->canServeProtocol($proto_https, false);
if ($can_http) {
switch ($repository->getVersionControlSystem()) {
case PhabricatorRepositoryType::REPOSITORY_TYPE_GIT:
$binaries[] = 'git-http-backend';
break;
case PhabricatorRepositoryType::REPOSITORY_TYPE_SVN:
$binaries[] = 'svnserve';
$binaries[] = 'svnadmin';
$binaries[] = 'svnlook';
$svnlook_check = true;
break;
case PhabricatorRepositoryType::REPOSITORY_TYPE_MERCURIAL:
$binaries[] = 'hg';
break;
}
}
$proto_ssh = PhabricatorRepositoryURI::BUILTIN_PROTOCOL_SSH;
$can_ssh = $repository->canServeProtocol($proto_ssh, false);
if ($can_ssh) {
switch ($repository->getVersionControlSystem()) {
case PhabricatorRepositoryType::REPOSITORY_TYPE_GIT:
$binaries[] = 'git-receive-pack';
$binaries[] = 'git-upload-pack';
break;
case PhabricatorRepositoryType::REPOSITORY_TYPE_SVN:
$binaries[] = 'svnserve';
$binaries[] = 'svnadmin';
$binaries[] = 'svnlook';
$svnlook_check = true;
break;
case PhabricatorRepositoryType::REPOSITORY_TYPE_MERCURIAL:
$binaries[] = 'hg';
break;
}
}
}
$binaries = array_unique($binaries);
if (!$is_cluster) {
// We're only checking for binaries if we aren't running with a cluster
// configuration. In theory, we could check for binaries on the
// repository host machine, but we'd need to make this more complicated
// to do that.
foreach ($binaries as $binary) {
$where = Filesystem::resolveBinary($binary);
if (!$where) {
$view->addItem(
id(new PHUIStatusItemView())
->setIcon(PHUIStatusItemView::ICON_WARNING, 'red')
->setTarget(
pht('Missing Binary %s', phutil_tag('tt', array(), $binary)))
->setNote(pht(
"Unable to find this binary in the webserver's PATH. You may ".
"need to configure %s.",
$this->getEnvConfigLink())));
} else {
$view->addItem(
id(new PHUIStatusItemView())
->setIcon(PHUIStatusItemView::ICON_ACCEPT, 'green')
->setTarget(
pht('Found Binary %s', phutil_tag('tt', array(), $binary)))
->setNote(phutil_tag('tt', array(), $where)));
}
}
// This gets checked generically above. However, for svn commit hooks, we
// need this to be in environment.append-paths because subversion strips
// PATH.
if ($svnlook_check) {
$where = Filesystem::resolveBinary('svnlook');
if ($where) {
$path = substr($where, 0, strlen($where) - strlen('svnlook'));
$dirs = PhabricatorEnv::getEnvConfig('environment.append-paths');
$in_path = false;
foreach ($dirs as $dir) {
if (Filesystem::isDescendant($path, $dir)) {
$in_path = true;
break;
}
}
if (!$in_path) {
$view->addItem(
id(new PHUIStatusItemView())
->setIcon(PHUIStatusItemView::ICON_WARNING, 'red')
->setTarget(
pht('Missing Binary %s', phutil_tag('tt', array(), $binary)))
->setNote(pht(
'Unable to find this binary in `%s`. '.
'You need to configure %s and include %s.',
'environment.append-paths',
$this->getEnvConfigLink(),
$path)));
}
}
}
}
$doc_href = PhabricatorEnv::getDoclink('Managing Daemons with phd');
$daemon_instructions = pht(
'Use %s to start daemons. See %s.',
phutil_tag('tt', array(), 'bin/phd start'),
phutil_tag(
'a',
array(
'href' => $doc_href,
),
pht('Managing Daemons with phd')));
$pull_daemon = id(new PhabricatorDaemonLogQuery())
->setViewer(PhabricatorUser::getOmnipotentUser())
->withStatus(PhabricatorDaemonLogQuery::STATUS_ALIVE)
->withDaemonClasses(array('PhabricatorRepositoryPullLocalDaemon'))
->setLimit(1)
->execute();
if ($pull_daemon) {
// TODO: In a cluster environment, we need a daemon on this repository's
// host, specifically, and we aren't checking for that right now. This
// is a reasonable proxy for things being more-or-less correctly set up,
// though.
$view->addItem(
id(new PHUIStatusItemView())
->setIcon(PHUIStatusItemView::ICON_ACCEPT, 'green')
->setTarget(pht('Pull Daemon Running')));
} else {
$view->addItem(
id(new PHUIStatusItemView())
->setIcon(PHUIStatusItemView::ICON_WARNING, 'red')
->setTarget(pht('Pull Daemon Not Running'))
->setNote($daemon_instructions));
}
$task_daemon = id(new PhabricatorDaemonLogQuery())
->setViewer(PhabricatorUser::getOmnipotentUser())
->withStatus(PhabricatorDaemonLogQuery::STATUS_ALIVE)
->withDaemonClasses(array('PhabricatorTaskmasterDaemon'))
->setLimit(1)
->execute();
if ($task_daemon) {
$view->addItem(
id(new PHUIStatusItemView())
->setIcon(PHUIStatusItemView::ICON_ACCEPT, 'green')
->setTarget(pht('Task Daemon Running')));
} else {
$view->addItem(
id(new PHUIStatusItemView())
->setIcon(PHUIStatusItemView::ICON_WARNING, 'red')
->setTarget(pht('Task Daemon Not Running'))
->setNote($daemon_instructions));
}
if ($is_cluster) {
// Just omit this status check for now in cluster environments. We
// could make a service call and pull it from the repository host
// eventually.
} else if ($repository->usesLocalWorkingCopy()) {
$local_parent = dirname($repository->getLocalPath());
if (Filesystem::pathExists($local_parent)) {
$view->addItem(
id(new PHUIStatusItemView())
->setIcon(PHUIStatusItemView::ICON_ACCEPT, 'green')
->setTarget(pht('Storage Directory OK'))
->setNote(phutil_tag('tt', array(), $local_parent)));
} else {
$view->addItem(
id(new PHUIStatusItemView())
->setIcon(PHUIStatusItemView::ICON_WARNING, 'red')
->setTarget(pht('No Storage Directory'))
->setNote(
pht(
'Storage directory %s does not exist, or is not readable by '.
'the webserver. Create this directory or make it readable.',
phutil_tag('tt', array(), $local_parent))));
return $view;
}
$local_path = $repository->getLocalPath();
$message = idx($messages, PhabricatorRepositoryStatusMessage::TYPE_INIT);
if ($message) {
switch ($message->getStatusCode()) {
case PhabricatorRepositoryStatusMessage::CODE_ERROR:
$view->addItem(
id(new PHUIStatusItemView())
->setIcon(PHUIStatusItemView::ICON_WARNING, 'red')
->setTarget(pht('Initialization Error'))
->setNote($message->getParameter('message')));
return $view;
case PhabricatorRepositoryStatusMessage::CODE_OKAY:
if (Filesystem::pathExists($local_path)) {
$view->addItem(
id(new PHUIStatusItemView())
->setIcon(PHUIStatusItemView::ICON_ACCEPT, 'green')
->setTarget(pht('Working Copy OK'))
->setNote(phutil_tag('tt', array(), $local_path)));
} else {
$view->addItem(
id(new PHUIStatusItemView())
->setIcon(PHUIStatusItemView::ICON_WARNING, 'red')
->setTarget(pht('Working Copy Error'))
->setNote(
pht(
'Working copy %s has been deleted, or is not '.
'readable by the webserver. Make this directory '.
'readable. If it has been deleted, the daemons should '.
'restore it automatically.',
phutil_tag('tt', array(), $local_path))));
return $view;
}
break;
default:
$view->addItem(
id(new PHUIStatusItemView())
->setIcon(PHUIStatusItemView::ICON_CLOCK, 'green')
->setTarget(pht('Initializing Working Copy'))
->setNote(pht('Daemons are initializing the working copy.')));
return $view;
}
} else {
$view->addItem(
id(new PHUIStatusItemView())
->setIcon(PHUIStatusItemView::ICON_CLOCK, 'orange')
->setTarget(pht('No Working Copy Yet'))
->setNote(
pht('Waiting for daemons to build a working copy.')));
return $view;
}
}
$message = idx($messages, PhabricatorRepositoryStatusMessage::TYPE_FETCH);
if ($message) {
switch ($message->getStatusCode()) {
case PhabricatorRepositoryStatusMessage::CODE_ERROR:
$message = $message->getParameter('message');
$suggestion = null;
if (preg_match('/Permission denied \(publickey\)./', $message)) {
$suggestion = pht(
'Public Key Error: This error usually indicates that the '.
'keypair you have configured does not have permission to '.
'access the repository.');
}
$view->addItem(
id(new PHUIStatusItemView())
->setIcon(PHUIStatusItemView::ICON_WARNING, 'red')
->setTarget(pht('Update Error'))
->setNote($suggestion));
return $view;
case PhabricatorRepositoryStatusMessage::CODE_OKAY:
$ago = (PhabricatorTime::getNow() - $message->getEpoch());
$view->addItem(
id(new PHUIStatusItemView())
->setIcon(PHUIStatusItemView::ICON_ACCEPT, 'green')
->setTarget(pht('Updates OK'))
->setNote(
pht(
'Last updated %s (%s ago).',
phabricator_datetime($message->getEpoch(), $viewer),
phutil_format_relative_time_detailed($ago))));
break;
}
} else {
$view->addItem(
id(new PHUIStatusItemView())
->setIcon(PHUIStatusItemView::ICON_CLOCK, 'orange')
->setTarget(pht('Waiting For Update'))
->setNote(
pht('Waiting for daemons to read updates.')));
}
if ($repository->isImporting()) {
$ratio = $repository->loadImportProgress();
$percentage = sprintf('%.2f%%', 100 * $ratio);
$view->addItem(
id(new PHUIStatusItemView())
->setIcon(PHUIStatusItemView::ICON_CLOCK, 'green')
->setTarget(pht('Importing'))
->setNote(
pht('%s Complete', $percentage)));
} else {
$view->addItem(
id(new PHUIStatusItemView())
->setIcon(PHUIStatusItemView::ICON_ACCEPT, 'green')
->setTarget(pht('Fully Imported')));
}
if (idx($messages, PhabricatorRepositoryStatusMessage::TYPE_NEEDS_UPDATE)) {
$view->addItem(
id(new PHUIStatusItemView())
->setIcon(PHUIStatusItemView::ICON_UP, 'indigo')
->setTarget(pht('Prioritized'))
->setNote(pht('This repository will be updated soon!')));
}
return $view;
}
private function buildRepositoryRawError(
PhabricatorRepository $repository,
array $messages) {
$viewer = $this->getViewer();
$can_edit = PhabricatorPolicyFilter::hasCapability(
$viewer,
$repository,
PhabricatorPolicyCapability::CAN_EDIT);
$raw_error = null;
$message = idx($messages, PhabricatorRepositoryStatusMessage::TYPE_FETCH);
if ($message) {
switch ($message->getStatusCode()) {
case PhabricatorRepositoryStatusMessage::CODE_ERROR:
$raw_error = $message->getParameter('message');
break;
}
}
if ($raw_error !== null) {
if (!$can_edit) {
$raw_message = pht(
'You must be able to edit a repository to see raw error messages '.
'because they sometimes disclose sensitive information.');
$raw_message = phutil_tag('em', array(), $raw_message);
} else {
$raw_message = phutil_escape_html_newlines($raw_error);
}
} else {
$raw_message = null;
}
return $raw_message;
}
private function loadStatusMessages(PhabricatorRepository $repository) {
$messages = id(new PhabricatorRepositoryStatusMessage())
->loadAllWhere('repositoryID = %d', $repository->getID());
$messages = mpull($messages, null, 'getStatusType');
return $messages;
}
private function getEnvConfigLink() {
$config_href = '/config/edit/environment.append-paths/';
return phutil_tag(
'a',
array(
'href' => $config_href,
),
'environment.append-paths');
}
} }

View file

@ -19,18 +19,7 @@ final class DiffusionRepositoryBranchesManagementPanel
} }
public function getManagementPanelIcon() { public function getManagementPanelIcon() {
$repository = $this->getRepository(); return 'fa-code-fork';
$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() { protected function getEditEngineFieldKeys() {
@ -41,29 +30,6 @@ final class DiffusionRepositoryBranchesManagementPanel
); );
} }
public function buildManagementPanelCurtain() {
$repository = $this->getRepository();
$viewer = $this->getViewer();
$action_list = $this->getNewActionList();
$can_edit = PhabricatorPolicyFilter::hasCapability(
$viewer,
$repository,
PhabricatorPolicyCapability::CAN_EDIT);
$branches_uri = $this->getEditPageURI();
$action_list->addAction(
id(new PhabricatorActionView())
->setIcon('fa-pencil')
->setName(pht('Edit Branches'))
->setHref($branches_uri)
->setDisabled(!$can_edit)
->setWorkflow(!$can_edit));
return $this->getNewCurtainView($action_list);
}
public function buildManagementPanelContent() { public function buildManagementPanelContent() {
$repository = $this->getRepository(); $repository = $this->getRepository();
$viewer = $this->getViewer(); $viewer = $this->getViewer();
@ -94,7 +60,23 @@ final class DiffusionRepositoryBranchesManagementPanel
} }
$view->addProperty(pht('Autoclose Only'), $autoclose_only); $view->addProperty(pht('Autoclose Only'), $autoclose_only);
$content[] = $this->newBox(pht('Branches'), $view);
$can_edit = PhabricatorPolicyFilter::hasCapability(
$viewer,
$repository,
PhabricatorPolicyCapability::CAN_EDIT);
$branches_uri = $this->getEditPageURI();
$button = id(new PHUIButtonView())
->setTag('a')
->setIcon('fa-pencil')
->setText(pht('Edit'))
->setHref($branches_uri)
->setDisabled(!$can_edit)
->setWorkflow(!$can_edit);
$content[] = $this->newBox(pht('Branches'), $view, array($button));
// Branch Autoclose Table // Branch Autoclose Table
if (!$repository->isImporting()) { if (!$repository->isImporting()) {
@ -176,11 +158,8 @@ final class DiffusionRepositoryBranchesManagementPanel
true, true,
)); ));
$box = id(new PHUIObjectBoxView()) $box = $this->newBox(pht('Branch Status'), $branch_table);
->setHeaderText(pht('Branch Status')) $box->setPager($pager);
->setBackground(PHUIObjectBoxView::BLUE_PROPERTY)
->setTable($branch_table)
->setPager($pager);
$content[] = $box; $content[] = $box;
} else { } else {
$content[] = id(new PHUIInfoView()) $content[] = id(new PHUIInfoView())

View file

@ -1,33 +0,0 @@
<?php
final class DiffusionRepositoryDocumentationManagementPanel
extends DiffusionRepositoryManagementPanel {
const PANELKEY = 'documentation';
public function getManagementPanelLabel() {
return pht('Documentation');
}
public function getManagementPanelOrder() {
return 3000;
}
public function getManagementPanelIcon() {
return 'fa-book';
}
public function buildManagementPanelContent() {
return null;
}
public function buildManagementPanelCurtain() {
return null;
}
public function getPanelNavigationURI() {
return PhabricatorEnv::getDoclink(
'Diffusion User Guide: Managing Repositories');
}
}

View file

@ -21,8 +21,4 @@ final class DiffusionRepositoryHistoryManagementPanel
return $this->newTimeline(); return $this->newTimeline();
} }
public function buildManagementPanelCurtain() {
return null;
}
} }

View file

@ -41,7 +41,6 @@ abstract class DiffusionRepositoryManagementPanel
abstract public function getManagementPanelLabel(); abstract public function getManagementPanelLabel();
abstract public function getManagementPanelOrder(); abstract public function getManagementPanelOrder();
abstract public function buildManagementPanelContent(); abstract public function buildManagementPanelContent();
abstract public function buildManagementPanelCurtain();
public function getManagementPanelIcon() { public function getManagementPanelIcon() {
return 'fa-pencil'; return 'fa-pencil';
@ -56,22 +55,6 @@ abstract class DiffusionRepositoryManagementPanel
return true; return true;
} }
public function getNewActionList() {
$viewer = $this->getViewer();
$action_id = celerity_generate_unique_node_id();
return id(new PhabricatorActionListView())
->setViewer($viewer)
->setID($action_id);
}
public function getNewCurtainView(PhabricatorActionListView $action_list) {
$viewer = $this->getViewer();
return id(new PHUICurtainView())
->setViewer($viewer)
->setActionList($action_list);
}
public static function getAllPanels() { public static function getAllPanels() {
return id(new PhutilClassMapQuery()) return id(new PhutilClassMapQuery())
->setAncestorClass(__CLASS__) ->setAncestorClass(__CLASS__)
@ -80,11 +63,20 @@ abstract class DiffusionRepositoryManagementPanel
->execute(); ->execute();
} }
final protected function newBox($header_text, $body) { final protected function newBox($header_text, $body, $button = array()) {
return id(new PHUIObjectBoxView()) $header = id(new PHUIHeaderView())
->setHeaderText($header_text) ->setHeader($header_text);
->setBackground(PHUIObjectBoxView::BLUE_PROPERTY)
foreach ($button as $link) {
$header->addActionLink($link);
}
$view = id(new PHUIObjectBoxView())
->setHeader($header)
->setBackground(PHUIObjectBoxView::WHITE_CONFIG)
->appendChild($body); ->appendChild($body);
return $view;
} }
final protected function newTimeline() { final protected function newTimeline() {

View file

@ -14,35 +14,7 @@ final class DiffusionRepositoryPoliciesManagementPanel
} }
public function getManagementPanelIcon() { public function getManagementPanelIcon() {
$viewer = $this->getViewer(); return 'fa-lock';
$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() { protected function getEditEngineFieldKeys() {
@ -54,29 +26,6 @@ final class DiffusionRepositoryPoliciesManagementPanel
); );
} }
public function buildManagementPanelCurtain() {
$repository = $this->getRepository();
$viewer = $this->getViewer();
$action_list = $this->getNewActionList();
$can_edit = PhabricatorPolicyFilter::hasCapability(
$viewer,
$repository,
PhabricatorPolicyCapability::CAN_EDIT);
$edit_uri = $this->getEditPageURI();
$action_list->addAction(
id(new PhabricatorActionView())
->setIcon('fa-pencil')
->setName(pht('Edit Policies'))
->setHref($edit_uri)
->setDisabled(!$can_edit)
->setWorkflow(!$can_edit));
return $this->getNewCurtainView($action_list);
}
public function buildManagementPanelContent() { public function buildManagementPanelContent() {
$repository = $this->getRepository(); $repository = $this->getRepository();
$viewer = $this->getViewer(); $viewer = $this->getViewer();
@ -109,7 +58,22 @@ final class DiffusionRepositoryPoliciesManagementPanel
: phutil_tag('em', array(), pht('Not a Hosted Repository')); : phutil_tag('em', array(), pht('Not a Hosted Repository'));
$view->addProperty(pht('Pushable By'), $pushable); $view->addProperty(pht('Pushable By'), $pushable);
return $this->newBox(pht('Policies'), $view); $can_edit = PhabricatorPolicyFilter::hasCapability(
$viewer,
$repository,
PhabricatorPolicyCapability::CAN_EDIT);
$edit_uri = $this->getEditPageURI();
$button = id(new PHUIButtonView())
->setTag('a')
->setIcon('fa-pencil')
->setText(pht('Edit'))
->setHref($edit_uri)
->setDisabled(!$can_edit)
->setWorkflow(!$can_edit);
return $this->newBox(pht('Policies'), $view, array($button));
} }
} }

View file

@ -20,15 +20,7 @@ final class DiffusionRepositoryStagingManagementPanel
public function getManagementPanelIcon() { public function getManagementPanelIcon() {
$repository = $this->getRepository(); return 'fa-upload';
$staging_uri = $repository->getStagingURI();
if ($staging_uri) {
return 'fa-upload';
} else {
return 'fa-upload grey';
}
} }
protected function getEditEngineFieldKeys() { protected function getEditEngineFieldKeys() {
@ -37,29 +29,6 @@ final class DiffusionRepositoryStagingManagementPanel
); );
} }
public function buildManagementPanelCurtain() {
$repository = $this->getRepository();
$viewer = $this->getViewer();
$action_list = $this->getNewActionList();
$can_edit = PhabricatorPolicyFilter::hasCapability(
$viewer,
$repository,
PhabricatorPolicyCapability::CAN_EDIT);
$staging_uri = $this->getEditPageURI();
$action_list->addAction(
id(new PhabricatorActionView())
->setIcon('fa-pencil')
->setName(pht('Edit Staging'))
->setHref($staging_uri)
->setDisabled(!$can_edit)
->setWorkflow(!$can_edit));
return $this->getNewCurtainView($action_list);
}
public function buildManagementPanelContent() { public function buildManagementPanelContent() {
$repository = $this->getRepository(); $repository = $this->getRepository();
$viewer = $this->getViewer(); $viewer = $this->getViewer();
@ -74,7 +43,22 @@ final class DiffusionRepositoryStagingManagementPanel
$view->addProperty(pht('Staging Area URI'), $staging_uri); $view->addProperty(pht('Staging Area URI'), $staging_uri);
return $this->newBox(pht('Staging Area'), $view); $can_edit = PhabricatorPolicyFilter::hasCapability(
$viewer,
$repository,
PhabricatorPolicyCapability::CAN_EDIT);
$staging_uri = $this->getEditPageURI();
$button = id(new PHUIButtonView())
->setTag('a')
->setIcon('fa-pencil')
->setText(pht('Edit'))
->setHref($staging_uri)
->setDisabled(!$can_edit)
->setWorkflow(!$can_edit);
return $this->newBox(pht('Staging Area'), $view, array($button));
} }
} }

View file

@ -1,507 +0,0 @@
<?php
final class DiffusionRepositoryStatusManagementPanel
extends DiffusionRepositoryManagementPanel {
const PANELKEY = 'status';
public function getManagementPanelLabel() {
return pht('Status');
}
public function getManagementPanelOrder() {
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';
}
public function buildManagementPanelCurtain() {
$repository = $this->getRepository();
$viewer = $this->getViewer();
$action_list = $this->getNewActionList();
$can_edit = PhabricatorPolicyFilter::hasCapability(
$viewer,
$repository,
PhabricatorPolicyCapability::CAN_EDIT);
$update_uri = $repository->getPathURI('edit/update/');
$action_list->addAction(
id(new PhabricatorActionView())
->setIcon('fa-refresh')
->setName(pht('Update Now'))
->setWorkflow(true)
->setDisabled(!$can_edit)
->setHref($update_uri));
return $this->getNewCurtainView($action_list);
}
public function buildManagementPanelContent() {
$repository = $this->getRepository();
$viewer = $this->getViewer();
$view = id(new PHUIPropertyListView())
->setViewer($viewer);
$view->addProperty(
pht('Update Frequency'),
$this->buildRepositoryUpdateInterval($repository));
$messages = $this->loadStatusMessages($repository);
$status = $this->buildRepositoryStatus($repository, $messages);
$raw_error = $this->buildRepositoryRawError($repository, $messages);
$view->addProperty(pht('Status'), $status);
if ($raw_error) {
$view->addSectionHeader(pht('Raw Error'));
$view->addTextContent($raw_error);
}
return $this->newBox(pht('Status'), $view);
}
private function buildRepositoryUpdateInterval(
PhabricatorRepository $repository) {
$smart_wait = $repository->loadUpdateInterval();
$doc_href = PhabricatorEnv::getDoclink(
'Diffusion User Guide: Repository Updates');
return array(
phutil_format_relative_time_detailed($smart_wait),
" \xC2\xB7 ",
phutil_tag(
'a',
array(
'href' => $doc_href,
'target' => '_blank',
),
pht('Learn More')),
);
}
private function buildRepositoryStatus(
PhabricatorRepository $repository,
array $messages) {
$viewer = $this->getViewer();
$is_cluster = $repository->getAlmanacServicePHID();
$view = new PHUIStatusListView();
if ($repository->isTracked()) {
$view->addItem(
id(new PHUIStatusItemView())
->setIcon(PHUIStatusItemView::ICON_ACCEPT, 'green')
->setTarget(pht('Repository Active')));
} else {
$view->addItem(
id(new PHUIStatusItemView())
->setIcon(PHUIStatusItemView::ICON_WARNING, 'bluegrey')
->setTarget(pht('Repository Inactive'))
->setNote(
pht('Activate this repository to begin or resume import.')));
return $view;
}
$binaries = array();
$svnlook_check = false;
switch ($repository->getVersionControlSystem()) {
case PhabricatorRepositoryType::REPOSITORY_TYPE_GIT:
$binaries[] = 'git';
break;
case PhabricatorRepositoryType::REPOSITORY_TYPE_SVN:
$binaries[] = 'svn';
break;
case PhabricatorRepositoryType::REPOSITORY_TYPE_MERCURIAL:
$binaries[] = 'hg';
break;
}
if ($repository->isHosted()) {
$proto_https = PhabricatorRepositoryURI::BUILTIN_PROTOCOL_HTTPS;
$proto_http = PhabricatorRepositoryURI::BUILTIN_PROTOCOL_HTTP;
$can_http = $repository->canServeProtocol($proto_http, false) ||
$repository->canServeProtocol($proto_https, false);
if ($can_http) {
switch ($repository->getVersionControlSystem()) {
case PhabricatorRepositoryType::REPOSITORY_TYPE_GIT:
$binaries[] = 'git-http-backend';
break;
case PhabricatorRepositoryType::REPOSITORY_TYPE_SVN:
$binaries[] = 'svnserve';
$binaries[] = 'svnadmin';
$binaries[] = 'svnlook';
$svnlook_check = true;
break;
case PhabricatorRepositoryType::REPOSITORY_TYPE_MERCURIAL:
$binaries[] = 'hg';
break;
}
}
$proto_ssh = PhabricatorRepositoryURI::BUILTIN_PROTOCOL_SSH;
$can_ssh = $repository->canServeProtocol($proto_ssh, false);
if ($can_ssh) {
switch ($repository->getVersionControlSystem()) {
case PhabricatorRepositoryType::REPOSITORY_TYPE_GIT:
$binaries[] = 'git-receive-pack';
$binaries[] = 'git-upload-pack';
break;
case PhabricatorRepositoryType::REPOSITORY_TYPE_SVN:
$binaries[] = 'svnserve';
$binaries[] = 'svnadmin';
$binaries[] = 'svnlook';
$svnlook_check = true;
break;
case PhabricatorRepositoryType::REPOSITORY_TYPE_MERCURIAL:
$binaries[] = 'hg';
break;
}
}
}
$binaries = array_unique($binaries);
if (!$is_cluster) {
// We're only checking for binaries if we aren't running with a cluster
// configuration. In theory, we could check for binaries on the
// repository host machine, but we'd need to make this more complicated
// to do that.
foreach ($binaries as $binary) {
$where = Filesystem::resolveBinary($binary);
if (!$where) {
$view->addItem(
id(new PHUIStatusItemView())
->setIcon(PHUIStatusItemView::ICON_WARNING, 'red')
->setTarget(
pht('Missing Binary %s', phutil_tag('tt', array(), $binary)))
->setNote(pht(
"Unable to find this binary in the webserver's PATH. You may ".
"need to configure %s.",
$this->getEnvConfigLink())));
} else {
$view->addItem(
id(new PHUIStatusItemView())
->setIcon(PHUIStatusItemView::ICON_ACCEPT, 'green')
->setTarget(
pht('Found Binary %s', phutil_tag('tt', array(), $binary)))
->setNote(phutil_tag('tt', array(), $where)));
}
}
// This gets checked generically above. However, for svn commit hooks, we
// need this to be in environment.append-paths because subversion strips
// PATH.
if ($svnlook_check) {
$where = Filesystem::resolveBinary('svnlook');
if ($where) {
$path = substr($where, 0, strlen($where) - strlen('svnlook'));
$dirs = PhabricatorEnv::getEnvConfig('environment.append-paths');
$in_path = false;
foreach ($dirs as $dir) {
if (Filesystem::isDescendant($path, $dir)) {
$in_path = true;
break;
}
}
if (!$in_path) {
$view->addItem(
id(new PHUIStatusItemView())
->setIcon(PHUIStatusItemView::ICON_WARNING, 'red')
->setTarget(
pht('Missing Binary %s', phutil_tag('tt', array(), $binary)))
->setNote(pht(
'Unable to find this binary in `%s`. '.
'You need to configure %s and include %s.',
'environment.append-paths',
$this->getEnvConfigLink(),
$path)));
}
}
}
}
$doc_href = PhabricatorEnv::getDoclink('Managing Daemons with phd');
$daemon_instructions = pht(
'Use %s to start daemons. See %s.',
phutil_tag('tt', array(), 'bin/phd start'),
phutil_tag(
'a',
array(
'href' => $doc_href,
),
pht('Managing Daemons with phd')));
$pull_daemon = id(new PhabricatorDaemonLogQuery())
->setViewer(PhabricatorUser::getOmnipotentUser())
->withStatus(PhabricatorDaemonLogQuery::STATUS_ALIVE)
->withDaemonClasses(array('PhabricatorRepositoryPullLocalDaemon'))
->setLimit(1)
->execute();
if ($pull_daemon) {
// TODO: In a cluster environment, we need a daemon on this repository's
// host, specifically, and we aren't checking for that right now. This
// is a reasonable proxy for things being more-or-less correctly set up,
// though.
$view->addItem(
id(new PHUIStatusItemView())
->setIcon(PHUIStatusItemView::ICON_ACCEPT, 'green')
->setTarget(pht('Pull Daemon Running')));
} else {
$view->addItem(
id(new PHUIStatusItemView())
->setIcon(PHUIStatusItemView::ICON_WARNING, 'red')
->setTarget(pht('Pull Daemon Not Running'))
->setNote($daemon_instructions));
}
$task_daemon = id(new PhabricatorDaemonLogQuery())
->setViewer(PhabricatorUser::getOmnipotentUser())
->withStatus(PhabricatorDaemonLogQuery::STATUS_ALIVE)
->withDaemonClasses(array('PhabricatorTaskmasterDaemon'))
->setLimit(1)
->execute();
if ($task_daemon) {
$view->addItem(
id(new PHUIStatusItemView())
->setIcon(PHUIStatusItemView::ICON_ACCEPT, 'green')
->setTarget(pht('Task Daemon Running')));
} else {
$view->addItem(
id(new PHUIStatusItemView())
->setIcon(PHUIStatusItemView::ICON_WARNING, 'red')
->setTarget(pht('Task Daemon Not Running'))
->setNote($daemon_instructions));
}
if ($is_cluster) {
// Just omit this status check for now in cluster environments. We
// could make a service call and pull it from the repository host
// eventually.
} else if ($repository->usesLocalWorkingCopy()) {
$local_parent = dirname($repository->getLocalPath());
if (Filesystem::pathExists($local_parent)) {
$view->addItem(
id(new PHUIStatusItemView())
->setIcon(PHUIStatusItemView::ICON_ACCEPT, 'green')
->setTarget(pht('Storage Directory OK'))
->setNote(phutil_tag('tt', array(), $local_parent)));
} else {
$view->addItem(
id(new PHUIStatusItemView())
->setIcon(PHUIStatusItemView::ICON_WARNING, 'red')
->setTarget(pht('No Storage Directory'))
->setNote(
pht(
'Storage directory %s does not exist, or is not readable by '.
'the webserver. Create this directory or make it readable.',
phutil_tag('tt', array(), $local_parent))));
return $view;
}
$local_path = $repository->getLocalPath();
$message = idx($messages, PhabricatorRepositoryStatusMessage::TYPE_INIT);
if ($message) {
switch ($message->getStatusCode()) {
case PhabricatorRepositoryStatusMessage::CODE_ERROR:
$view->addItem(
id(new PHUIStatusItemView())
->setIcon(PHUIStatusItemView::ICON_WARNING, 'red')
->setTarget(pht('Initialization Error'))
->setNote($message->getParameter('message')));
return $view;
case PhabricatorRepositoryStatusMessage::CODE_OKAY:
if (Filesystem::pathExists($local_path)) {
$view->addItem(
id(new PHUIStatusItemView())
->setIcon(PHUIStatusItemView::ICON_ACCEPT, 'green')
->setTarget(pht('Working Copy OK'))
->setNote(phutil_tag('tt', array(), $local_path)));
} else {
$view->addItem(
id(new PHUIStatusItemView())
->setIcon(PHUIStatusItemView::ICON_WARNING, 'red')
->setTarget(pht('Working Copy Error'))
->setNote(
pht(
'Working copy %s has been deleted, or is not '.
'readable by the webserver. Make this directory '.
'readable. If it has been deleted, the daemons should '.
'restore it automatically.',
phutil_tag('tt', array(), $local_path))));
return $view;
}
break;
default:
$view->addItem(
id(new PHUIStatusItemView())
->setIcon(PHUIStatusItemView::ICON_CLOCK, 'green')
->setTarget(pht('Initializing Working Copy'))
->setNote(pht('Daemons are initializing the working copy.')));
return $view;
}
} else {
$view->addItem(
id(new PHUIStatusItemView())
->setIcon(PHUIStatusItemView::ICON_CLOCK, 'orange')
->setTarget(pht('No Working Copy Yet'))
->setNote(
pht('Waiting for daemons to build a working copy.')));
return $view;
}
}
$message = idx($messages, PhabricatorRepositoryStatusMessage::TYPE_FETCH);
if ($message) {
switch ($message->getStatusCode()) {
case PhabricatorRepositoryStatusMessage::CODE_ERROR:
$message = $message->getParameter('message');
$suggestion = null;
if (preg_match('/Permission denied \(publickey\)./', $message)) {
$suggestion = pht(
'Public Key Error: This error usually indicates that the '.
'keypair you have configured does not have permission to '.
'access the repository.');
}
$view->addItem(
id(new PHUIStatusItemView())
->setIcon(PHUIStatusItemView::ICON_WARNING, 'red')
->setTarget(pht('Update Error'))
->setNote($suggestion));
return $view;
case PhabricatorRepositoryStatusMessage::CODE_OKAY:
$ago = (PhabricatorTime::getNow() - $message->getEpoch());
$view->addItem(
id(new PHUIStatusItemView())
->setIcon(PHUIStatusItemView::ICON_ACCEPT, 'green')
->setTarget(pht('Updates OK'))
->setNote(
pht(
'Last updated %s (%s ago).',
phabricator_datetime($message->getEpoch(), $viewer),
phutil_format_relative_time_detailed($ago))));
break;
}
} else {
$view->addItem(
id(new PHUIStatusItemView())
->setIcon(PHUIStatusItemView::ICON_CLOCK, 'orange')
->setTarget(pht('Waiting For Update'))
->setNote(
pht('Waiting for daemons to read updates.')));
}
if ($repository->isImporting()) {
$ratio = $repository->loadImportProgress();
$percentage = sprintf('%.2f%%', 100 * $ratio);
$view->addItem(
id(new PHUIStatusItemView())
->setIcon(PHUIStatusItemView::ICON_CLOCK, 'green')
->setTarget(pht('Importing'))
->setNote(
pht('%s Complete', $percentage)));
} else {
$view->addItem(
id(new PHUIStatusItemView())
->setIcon(PHUIStatusItemView::ICON_ACCEPT, 'green')
->setTarget(pht('Fully Imported')));
}
if (idx($messages, PhabricatorRepositoryStatusMessage::TYPE_NEEDS_UPDATE)) {
$view->addItem(
id(new PHUIStatusItemView())
->setIcon(PHUIStatusItemView::ICON_UP, 'indigo')
->setTarget(pht('Prioritized'))
->setNote(pht('This repository will be updated soon!')));
}
return $view;
}
private function buildRepositoryRawError(
PhabricatorRepository $repository,
array $messages) {
$viewer = $this->getViewer();
$can_edit = PhabricatorPolicyFilter::hasCapability(
$viewer,
$repository,
PhabricatorPolicyCapability::CAN_EDIT);
$raw_error = null;
$message = idx($messages, PhabricatorRepositoryStatusMessage::TYPE_FETCH);
if ($message) {
switch ($message->getStatusCode()) {
case PhabricatorRepositoryStatusMessage::CODE_ERROR:
$raw_error = $message->getParameter('message');
break;
}
}
if ($raw_error !== null) {
if (!$can_edit) {
$raw_message = pht(
'You must be able to edit a repository to see raw error messages '.
'because they sometimes disclose sensitive information.');
$raw_message = phutil_tag('em', array(), $raw_message);
} else {
$raw_message = phutil_escape_html_newlines($raw_error);
}
} else {
$raw_message = null;
}
return $raw_message;
}
private function loadStatusMessages(PhabricatorRepository $repository) {
$messages = id(new PhabricatorRepositoryStatusMessage())
->loadAllWhere('repositoryID = %d', $repository->getID());
$messages = mpull($messages, null, 'getStatusType');
return $messages;
}
private function getEnvConfigLink() {
$config_href = '/config/edit/environment.append-paths/';
return phutil_tag(
'a',
array(
'href' => $config_href,
),
'environment.append-paths');
}
}

View file

@ -14,31 +14,7 @@ final class DiffusionRepositoryStorageManagementPanel
} }
public function getManagementPanelIcon() { public function getManagementPanelIcon() {
$repository = $this->getRepository(); return 'fa-database';
if ($repository->getAlmanacServicePHID()) {
return 'fa-sitemap';
} else if ($repository->isHosted()) {
return 'fa-folder';
} else {
return 'fa-download';
}
}
public function buildManagementPanelCurtain() {
$repository = $this->getRepository();
$viewer = $this->getViewer();
$action_list = $this->getNewActionList();
$doc_href = PhabricatorEnv::getDoclink('Cluster: Repositories');
$action_list->addAction(
id(new PhabricatorActionView())
->setIcon('fa-book')
->setHref($doc_href)
->setName(pht('Cluster Documentation')));
return $this->getNewCurtainView($action_list);
} }
public function buildManagementPanelContent() { public function buildManagementPanelContent() {
@ -71,9 +47,15 @@ final class DiffusionRepositoryStorageManagementPanel
$view->addProperty(pht('Storage Path'), $storage_path); $view->addProperty(pht('Storage Path'), $storage_path);
$view->addProperty(pht('Storage Cluster'), $storage_service); $view->addProperty(pht('Storage Cluster'), $storage_service);
$box = $this->newBox(pht('Storage'), null); $doc_href = PhabricatorEnv::getDoclink('Cluster: Repositories');
$box->addPropertyList($view);
return $box; $button = id(new PHUIButtonView())
->setTag('a')
->setIcon('fa-book')
->setHref($doc_href)
->setText(pht('Help'));
return $this->newBox(pht('Storage'), $view, array($button));
} }
private function buildClusterStatusPanel() { private function buildClusterStatusPanel() {
@ -243,9 +225,7 @@ final class DiffusionRepositoryStorageManagementPanel
'date', 'date',
)); ));
$box = $this->newBox(pht('Cluster Status'), null); return $this->newBox(pht('Cluster Status'), $table);
$box->setTable($table);
return $box;
} }
} }

View file

@ -19,15 +19,7 @@ final class DiffusionRepositorySubversionManagementPanel
} }
public function getManagementPanelIcon() { public function getManagementPanelIcon() {
$repository = $this->getRepository(); return 'fa-folder';
$has_any = (bool)$repository->getDetail('svn-subpath');
if ($has_any) {
return 'fa-database';
} else {
return 'fa-database grey';
}
} }
protected function getEditEngineFieldKeys() { protected function getEditEngineFieldKeys() {
@ -36,29 +28,6 @@ final class DiffusionRepositorySubversionManagementPanel
); );
} }
public function buildManagementPanelCurtain() {
$repository = $this->getRepository();
$viewer = $this->getViewer();
$action_list = $this->getNewActionList();
$can_edit = PhabricatorPolicyFilter::hasCapability(
$viewer,
$repository,
PhabricatorPolicyCapability::CAN_EDIT);
$subversion_uri = $this->getEditPageURI();
$action_list->addAction(
id(new PhabricatorActionView())
->setIcon('fa-pencil')
->setName(pht('Edit Properties'))
->setHref($subversion_uri)
->setDisabled(!$can_edit)
->setWorkflow(!$can_edit));
return $this->getNewCurtainView($action_list);
}
public function buildManagementPanelContent() { public function buildManagementPanelContent() {
$repository = $this->getRepository(); $repository = $this->getRepository();
$viewer = $this->getViewer(); $viewer = $this->getViewer();
@ -71,8 +40,22 @@ final class DiffusionRepositorySubversionManagementPanel
phutil_tag('em', array(), pht('Import Entire Repository'))); phutil_tag('em', array(), pht('Import Entire Repository')));
$view->addProperty(pht('Import Only'), $default_branch); $view->addProperty(pht('Import Only'), $default_branch);
$can_edit = PhabricatorPolicyFilter::hasCapability(
$viewer,
$repository,
PhabricatorPolicyCapability::CAN_EDIT);
return $this->newBox(pht('Subversion'), $view); $subversion_uri = $this->getEditPageURI();
$button = id(new PHUIButtonView())
->setTag('a')
->setIcon('fa-pencil')
->setText(pht('Edit'))
->setHref($subversion_uri)
->setDisabled(!$can_edit)
->setWorkflow(!$can_edit);
return $this->newBox(pht('Subversion'), $view, array($button));
} }
} }

View file

@ -14,17 +14,7 @@ final class DiffusionRepositorySymbolsManagementPanel
} }
public function getManagementPanelIcon() { public function getManagementPanelIcon() {
$repository = $this->getRepository(); return 'fa-bullseye';
$has_any =
$repository->getSymbolLanguages() ||
$repository->getSymbolSources();
if ($has_any) {
return 'fa-link';
} else {
return 'fa-link grey';
}
} }
protected function getEditEngineFieldKeys() { protected function getEditEngineFieldKeys() {
@ -34,29 +24,6 @@ final class DiffusionRepositorySymbolsManagementPanel
); );
} }
public function buildManagementPanelCurtain() {
$repository = $this->getRepository();
$viewer = $this->getViewer();
$action_list = $this->getNewActionList();
$can_edit = PhabricatorPolicyFilter::hasCapability(
$viewer,
$repository,
PhabricatorPolicyCapability::CAN_EDIT);
$symbols_uri = $this->getEditPageURI();
$action_list->addAction(
id(new PhabricatorActionView())
->setIcon('fa-pencil')
->setName(pht('Edit Symbols'))
->setHref($symbols_uri)
->setDisabled(!$can_edit)
->setWorkflow(!$can_edit));
return $this->getNewCurtainView($action_list);
}
public function buildManagementPanelContent() { public function buildManagementPanelContent() {
$repository = $this->getRepository(); $repository = $this->getRepository();
$viewer = $this->getViewer(); $viewer = $this->getViewer();
@ -80,7 +47,22 @@ final class DiffusionRepositorySymbolsManagementPanel
} }
$view->addProperty(pht('Uses Symbols From'), $sources); $view->addProperty(pht('Uses Symbols From'), $sources);
return $this->newBox(pht('Symbols'), $view); $can_edit = PhabricatorPolicyFilter::hasCapability(
$viewer,
$repository,
PhabricatorPolicyCapability::CAN_EDIT);
$symbols_uri = $this->getEditPageURI();
$button = id(new PHUIButtonView())
->setTag('a')
->setIcon('fa-pencil')
->setText(pht('Edit'))
->setHref($symbols_uri)
->setDisabled(!$can_edit)
->setWorkflow(!$can_edit);
return $this->newBox(pht('Symbols'), $view, array($button));
} }
} }

View file

@ -10,42 +10,13 @@ final class DiffusionRepositoryURIsManagementPanel
} }
public function getManagementPanelIcon() { public function getManagementPanelIcon() {
return 'fa-cogs'; return 'fa-globe';
} }
public function getManagementPanelOrder() { public function getManagementPanelOrder() {
return 400; return 400;
} }
public function buildManagementPanelCurtain() {
$repository = $this->getRepository();
$viewer = $this->getViewer();
$action_list = $this->getNewActionList();
$can_edit = PhabricatorPolicyFilter::hasCapability(
$viewer,
$repository,
PhabricatorPolicyCapability::CAN_EDIT);
$doc_href = PhabricatorEnv::getDoclink('Diffusion User Guide: URIs');
$add_href = $repository->getPathURI('uri/edit/');
$action_list->addAction(
id(new PhabricatorActionView())
->setIcon('fa-plus')
->setHref($add_href)
->setDisabled(!$can_edit)
->setName(pht('Add New URI')));
$action_list->addAction(
id(new PhabricatorActionView())
->setIcon('fa-book')
->setHref($doc_href)
->setName(pht('URI Documentation')));
return $this->getNewCurtainView($action_list);
}
public function buildManagementPanelContent() { public function buildManagementPanelContent() {
$repository = $this->getRepository(); $repository = $this->getRepository();
$viewer = $this->getViewer(); $viewer = $this->getViewer();
@ -151,10 +122,30 @@ final class DiffusionRepositoryURIsManagementPanel
->setSeverity(PHUIInfoView::SEVERITY_NOTICE) ->setSeverity(PHUIInfoView::SEVERITY_NOTICE)
->setErrors($messages); ->setErrors($messages);
$box = $this->newBox(pht('Repository URIs'), null); $can_edit = PhabricatorPolicyFilter::hasCapability(
$box->setTable($table); $viewer,
$repository,
PhabricatorPolicyCapability::CAN_EDIT);
return array($info_view, $box); $doc_href = PhabricatorEnv::getDoclink('Diffusion User Guide: URIs');
$add_href = $repository->getPathURI('uri/edit/');
$add = id(new PHUIButtonView())
->setTag('a')
->setIcon('fa-plus')
->setHref($add_href)
->setDisabled(!$can_edit)
->setText(pht('New URI'));
$help = id(new PHUIButtonView())
->setTag('a')
->setIcon('fa-book')
->setHref($doc_href)
->setText(pht('Help'));
$box = $this->newBox(pht('Repository URIs'), $table, array($add, $help));
return array($box, $info_view);
} }
} }

View file

@ -136,3 +136,8 @@ body .phui-box-blue-property .phui-header-shell + .phui-object-box {
.phui-box-white-config .phui-header-header { .phui-box-white-config .phui-header-header {
color: {$bluetext}; color: {$bluetext};
} }
.phui-box-white-config .phui-header-action-links .button {
margin-top: 0;
margin-bottom: 0;
}

View file

@ -337,6 +337,10 @@ body .phui-header-shell.phui-bleed-header
color: {$blacktext}; color: {$blacktext};
} }
.phui-profile-header.phui-header-shell .phui-header-header a {
color: {$blacktext};
}
.phui-profile-header .phui-header-col3 { .phui-profile-header .phui-header-col3 {
vertical-align: top; vertical-align: top;
} }