Christopher Johnson (WMDE) has submitted this change and it was merged. Change subject: updates to upstream 155cb1d2c5a8066e843f03e4ab3f8c91171e0305 many things changed due to new "profilePanel" menu ......................................................................
updates to upstream 155cb1d2c5a8066e843f03e4ab3f8c91171e0305 many things changed due to new "profilePanel" menu Change-Id: I94bec5bf20aca837ca742c2648c881cd6ed12b95 --- M src/__phutil_library_map__.php M src/controller/SprintController.php M src/controller/SprintDataViewController.php M src/controller/SprintProjectController.php M src/controller/SprintProjectProfileController.php M src/controller/board/SprintBoardColumnDetailController.php M src/controller/board/SprintBoardColumnEditController.php M src/controller/board/SprintBoardController.php M src/controller/board/SprintBoardViewController.php A src/engine/SprintProjectDetailsProfilePanel.php A src/engine/SprintProjectProfilePanelEngine.php A src/profilepanel/SprintProjectWorkboardProfilePanel.php 12 files changed, 314 insertions(+), 172 deletions(-) Approvals: Christopher Johnson (WMDE): Verified; Looks good to me, approved jenkins-bot: Verified diff --git a/src/__phutil_library_map__.php b/src/__phutil_library_map__.php index 3fa5040..de567d0 100644 --- a/src/__phutil_library_map__.php +++ b/src/__phutil_library_map__.php @@ -65,8 +65,11 @@ 'SprintPoints' => 'util/SprintPoints.php', 'SprintProjectController' => 'controller/SprintProjectController.php', 'SprintProjectCustomField' => 'customfield/SprintProjectCustomField.php', + 'SprintProjectDetailsProfilePanel' => 'engine/SprintProjectDetailsProfilePanel.php', 'SprintProjectProfileController' => 'controller/SprintProjectProfileController.php', + 'SprintProjectProfilePanelEngine' => 'engine/SprintProjectProfilePanelEngine.php', 'SprintProjectViewController' => 'controller/SprintProjectViewController.php', + 'SprintProjectWorkboardProfilePanel' => 'profilepanel/SprintProjectWorkboardProfilePanel.php', 'SprintQuery' => 'query/SprintQuery.php', 'SprintQueryTest' => 'tests/SprintQueryTest.php', 'SprintReportBurnUpView' => 'view/reports/SprintReportBurnUpView.php', @@ -105,7 +108,7 @@ 'SprintBoardColumnDetailController' => 'SprintBoardController', 'SprintBoardColumnEditController' => 'SprintBoardController', 'SprintBoardColumnHideController' => 'SprintBoardController', - 'SprintBoardController' => 'SprintController', + 'SprintBoardController' => 'SprintProjectController', 'SprintBoardImportController' => 'SprintBoardController', 'SprintBoardMoveController' => 'SprintBoardController', 'SprintBoardReorderController' => 'SprintBoardController', @@ -140,8 +143,11 @@ 'PhabricatorProjectCustomField', 'PhabricatorStandardCustomFieldInterface', ), + 'SprintProjectDetailsProfilePanel' => 'PhabricatorProfilePanel', 'SprintProjectProfileController' => 'SprintProjectController', + 'SprintProjectProfilePanelEngine' => 'PhabricatorProfilePanelEngine', 'SprintProjectViewController' => 'SprintController', + 'SprintProjectWorkboardProfilePanel' => 'PhabricatorProfilePanel', 'SprintQuery' => 'SprintDAO', 'SprintQueryTest' => 'SprintTestCase', 'SprintReportBurnUpView' => 'SprintView', diff --git a/src/controller/SprintController.php b/src/controller/SprintController.php index 02947e6..a05d625 100644 --- a/src/controller/SprintController.php +++ b/src/controller/SprintController.php @@ -118,62 +118,6 @@ return $id; } - public function buildIconNavView(PhabricatorProject $project) { - $nav = $this->buildSprintIconNavView($project); - $nav->selectFilter(null); - return $nav; - } - - public function buildSprintIconNavView(PhabricatorProject $project) { - $viewer = $this->getViewer(); - $id = $project->getID(); - $picture = $project->getProfileImageURI(); - $name = $project->getName(); - $enable_phragile = PhabricatorEnv::getEnvConfig('sprint.enable-phragile'); - $phragile_base_uri = PhabricatorEnv::getEnvConfig('sprint.phragile-uri'); - $phragile_uri = new PhutilURI($phragile_base_uri.$id); - $columns = id(new PhabricatorProjectColumnQuery()) - ->setViewer($viewer) - ->withProjectPHIDs(array($project->getPHID())) - ->execute(); - if ($columns) { - $board_icon = 'fa-columns'; - } else { - $board_icon = 'fa-columns grey'; - } - - $nav = new AphrontSideNavFilterView(); - $nav->setIconNav(true); - if ($this->isSprint($project) !== false) { - $nav->setBaseURI(new PhutilURI($this->getApplicationURI())); - $nav->addIcon("profile/{$id}/", $name, null, $picture, null); - $nav->addIcon("burn/{$id}/", pht('Burndown'), 'fa-fire', null, null); - if ($enable_phragile) { - $nav->addIcon("sprints/{$id}/", pht('Phragile'), 'fa-pie-chart', null, $phragile_uri); - } - $nav->addIcon("board/{$id}/", pht('Sprint Board'), $board_icon, null, null); - $nav->addIcon('.', pht('Sprint List'), 'fa-bar-chart', null, null); - } else { - $nav->setBaseURI(new PhutilURI($this->getProjectsURI())); - $nav->addIcon("profile/{$id}/", $name, null, $picture); - $nav->addIcon("board/{$id}/", pht('Workboard'), $board_icon); - } - $class = 'PhabricatorManiphestApplication'; - if (PhabricatorApplication::isClassInstalledForViewer($class, $viewer)) { - $phid = $project->getPHID(); - $query_uri = urisprintf( - '/maniphest/?statuses=open()&projects=%s#R', - $phid); - $nav->addIcon(null, pht('Open Tasks'), 'fa-anchor', null, $query_uri); - } - - $nav->addIcon("feed/{$id}/", pht('Feed'), 'fa-newspaper-o', null, null); - $nav->addIcon("members/{$id}/", pht('Members'), 'fa-group', null, null); - $nav->addIcon("edit/{$id}/", pht('Edit Details'), 'fa-pencil', null, null); - - return $nav; - } - protected function isSprint($object) { $validator = new SprintValidator(); $issprint = call_user_func(array($validator, 'checkForSprint'), diff --git a/src/controller/SprintDataViewController.php b/src/controller/SprintDataViewController.php index 50390f6..5113cff 100755 --- a/src/controller/SprintDataViewController.php +++ b/src/controller/SprintDataViewController.php @@ -6,12 +6,21 @@ private $request; private $viewer; private $project; + private $profileMenu; - public function buildIconNavView(PhabricatorProject $project) { - $id = $project->getID(); - $nav = parent::buildIconNavView($project); - $nav->selectFilter("burn/{$id}/"); - return $nav; + public function getProfileMenu(PhabricatorProject $project) { + if (!$this->profileMenu) { + if ($project) { + $viewer = $this->getViewer(); + + $engine = id(new SprintProjectProfilePanelEngine()) + ->setViewer($viewer) + ->setProfileObject($project); + + $this->profileMenu = $engine->buildNavigation(); + } + } + return $this->profileMenu; } public function handleRequest(AphrontRequest $request) { @@ -35,19 +44,14 @@ $can_create = $this->hasApplicationCapability( ProjectCreateProjectsCapability::CAPABILITY); $crumbs = $this->getCrumbs($can_create); - $nav = $this->buildIconNavView($this->project); - $nav->appendChild( - array($crumbs, - $error_box, - $sprintdata_view, - )); - - return $this->buildApplicationPage( - $nav, - array( - 'title' => array(pht('Burndown'), $this->project->getName()), - 'device' => true, - )); + $nav = $this->getProfileMenu($this->project); + return $this->newPage() + ->setNavigation($nav) + ->setCrumbs($crumbs) + ->setTitle($this->project->getName()) + ->setPageObjectPHIDs(array($this->project->getPHID())) + ->appendChild($error_box) + ->appendChild($sprintdata_view); } public function loadProject() { diff --git a/src/controller/SprintProjectController.php b/src/controller/SprintProjectController.php index 8866971..52a9eef 100644 --- a/src/controller/SprintProjectController.php +++ b/src/controller/SprintProjectController.php @@ -3,6 +3,7 @@ abstract class SprintProjectController extends SprintController { private $project; + private $profileMenu; protected function setProject(PhabricatorProject $project) { $this->project = $project; @@ -80,7 +81,33 @@ } public function buildApplicationMenu() { - return $this->buildSideNavView(true)->getMenu(); + $menu = $this->newApplicationMenu(); + + $profile_menu = $this->getProfileMenu(); + if ($profile_menu) { + $menu->setProfileMenu($profile_menu); + } + + $menu->setSearchEngine(new PhabricatorProjectSearchEngine()); + + return $menu; + } + + protected function getProfileMenu() { + if (!$this->profileMenu) { + $project = $this->getProject(); + if ($project) { + $viewer = $this->getViewer(); + + $engine = id(new SprintProjectProfilePanelEngine()) + ->setViewer($viewer) + ->setProfileObject($project); + + $this->profileMenu = $engine->buildNavigation(); + } + } + + return $this->profileMenu; } public function buildSideNavView($for_app = false) { @@ -111,66 +138,6 @@ } $nav->selectFilter(null); - - return $nav; - } - - public function buildIconNavView(PhabricatorProject $project) { - $this->setProject($project); - $viewer = $this->getViewer(); - $id = $project->getID(); - $picture = $project->getProfileImageURI(); - $name = $project->getName(); - $enable_phragile = PhabricatorEnv::getEnvConfig('sprint.enable-phragile'); - $phragile_base_uri = PhabricatorEnv::getEnvConfig('sprint.phragile-uri'); - $phragile_uri = new PhutilURI($phragile_base_uri.$id); - - $columns = id(new PhabricatorProjectColumnQuery()) - ->setViewer($viewer) - ->withProjectPHIDs(array($project->getPHID())) - ->execute(); - if ($columns) { - $board_icon = 'fa-columns'; - } else { - $board_icon = 'fa-columns grey'; - } - - $nav = new AphrontSideNavFilterView(); - $nav->setIconNav(true); - $nav->setBaseURI(new PhutilURI($this->getApplicationURI())); - if ($this->isSprint($project) !== false) { - $nav->setBaseURI(new PhutilURI($this->getApplicationURI())); - $nav->addIcon("profile/{$id}/", $name, null, $picture, null); - $nav->addIcon("burn/{$id}/", pht('Burndown'), 'fa-fire', null, null); - if ($enable_phragile) { - $nav->addIcon("sprints/{$id}/", pht('Phragile'), 'fa-pie-chart', null, $phragile_uri); - } - $nav->addIcon("board/{$id}/", pht('Sprint Board'), $board_icon, null, null); - $nav->addIcon('.', pht('Sprint List'), 'fa-bar-chart', null, null); - } else { - $nav->setBaseURI(new PhutilURI($this->getProjectsURI())); - $nav->addIcon("profile/{$id}/", $name, null, $picture); - $nav->addIcon("board/{$id}/", pht('Workboard'), $board_icon); - } - $class = 'PhabricatorManiphestApplication'; - if (PhabricatorApplication::isClassInstalledForViewer($class, $viewer)) { - $phid = $project->getPHID(); - - $query_uri = urisprintf( - '/maniphest/?statuses=open()&projects=%s#R', - $phid); - $nav->addIcon(null, pht('Open Tasks'), 'fa-anchor', null, $query_uri); - } - - $nav->addIcon("feed/{$id}/", pht('Feed'), 'fa-newspaper-o'); - $nav->addIcon("members/{$id}/", pht('Members'), 'fa-group'); - $nav->addIcon("details/{$id}/", pht('Edit Details'), 'fa-pencil'); - - if (PhabricatorEnv::getEnvConfig('phabricator.show-prototypes')) { - $nav->addIcon("subprojects/{$id}/", pht('Subprojects'), 'fa-sitemap'); - $nav->addIcon("milestones/{$id}/", pht('Milestones'), 'fa-map-marker'); - } - return $nav; } diff --git a/src/controller/SprintProjectProfileController.php b/src/controller/SprintProjectProfileController.php index addd70f..46d00a2 100644 --- a/src/controller/SprintProjectProfileController.php +++ b/src/controller/SprintProjectProfileController.php @@ -44,8 +44,8 @@ new PhabricatorProjectTransactionQuery()); $timeline->setShouldTerminate(true); - $nav = $this->buildIconNavView($project); - $nav->selectFilter("profile/{$id}/"); + $nav = $this->getProfileMenu(); + $nav->selectFilter(PhabricatorProject::PANEL_PROFILE); $crumbs = $this->buildApplicationCrumbs(); return $this->newPage() @@ -76,7 +76,9 @@ id(new PhabricatorActionView()) ->setName(pht('Edit Details')) ->setIcon('fa-pencil') - ->setHref($this->getApplicationURI("edit/{$id}/"))); + ->setHref($this->getApplicationURI("edit/{$id}/")) + ->setDisabled(!$can_edit) + ->setWorkflow(!$can_edit)); $view->addAction( id(new PhabricatorActionView()) @@ -104,6 +106,26 @@ ->setWorkflow(true)); } + $can_lock = $can_edit && $this->hasApplicationCapability( + ProjectCanLockProjectsCapability::CAPABILITY); + + if ($project->getIsMembershipLocked()) { + $lock_name = pht('Unlock Project'); + $lock_icon = 'fa-unlock'; + } else { + $lock_name = pht('Lock Project'); + $lock_icon = 'fa-lock'; + } + + $view->addAction( + id(new PhabricatorActionView()) + ->setName($lock_name) + ->setIcon($lock_icon) + ->setHref($this->getApplicationURI("lock/{$id}/")) + ->setDisabled(!$can_lock) + ->setWorkflow(true)); + + $action = null; if (!$project->isUserMember($viewer->getPHID())) { $can_join = PhabricatorPolicyFilter::hasCapability( $viewer, @@ -164,7 +186,9 @@ ->setName('#'.$slug->getSlug()); } - $view->addProperty(pht('Hashtags'), phutil_implode_html(' ', $hashtags)); + if ($hashtags) { + $view->addProperty(pht('Hashtags'), phutil_implode_html(' ', $hashtags)); + } $view->addProperty( pht('Members'), diff --git a/src/controller/board/SprintBoardColumnDetailController.php b/src/controller/board/SprintBoardColumnDetailController.php index 6f3bfc5..9e59ecf 100644 --- a/src/controller/board/SprintBoardColumnDetailController.php +++ b/src/controller/board/SprintBoardColumnDetailController.php @@ -50,15 +50,16 @@ ->setHeader($header) ->addPropertyList($properties); - $nav = $this->buildIconNavView($project); - $nav->appendChild($box); - $nav->appendChild($timeline); + $nav = $this->getProfileMenu(); - return $this->buildApplicationPage( - $nav, - array( - 'title' => $title, - )); + return $this->newPage() + ->setTitle($title) + ->setNavigation($nav) + ->appendChild( + array( + $box, + $timeline, + )); } private function buildHeaderView(PhabricatorProjectColumn $column) { diff --git a/src/controller/board/SprintBoardColumnEditController.php b/src/controller/board/SprintBoardColumnEditController.php index afd2ea5..3c79119 100644 --- a/src/controller/board/SprintBoardColumnEditController.php +++ b/src/controller/board/SprintBoardColumnEditController.php @@ -144,13 +144,11 @@ ->setValidationException($validation_exception) ->setForm($form); - $nav = $this->buildIconNavView($project); - $nav->appendChild($form_box); + $nav = $this->getProfileMenu(); - return $this->buildApplicationPage( - $nav, - array( - 'title' => $title, - )); + return $this->newPage() + ->setTitle($title) + ->setNavigation($nav) + ->appendChild($form_box); } } diff --git a/src/controller/board/SprintBoardController.php b/src/controller/board/SprintBoardController.php index 423a842..7fd1809 100644 --- a/src/controller/board/SprintBoardController.php +++ b/src/controller/board/SprintBoardController.php @@ -1,7 +1,7 @@ <?php abstract class SprintBoardController - extends SprintController { + extends SprintProjectController { private $project; @@ -13,11 +13,12 @@ return $this->project; } - public function buildIconNavView(PhabricatorProject $project) { - $id = $project->getID(); - $nav = parent::buildIconNavView($project); - $nav->selectFilter("board/{$id}/"); - $nav->addClass('project-board-nav'); - return $nav; + protected function getProfileMenu() { + $menu = parent::getProfileMenu(); + + $menu->selectFilter(PhabricatorProject::PANEL_WORKBOARD); + $menu->addClass('project-board-nav'); + + return $menu; } } diff --git a/src/controller/board/SprintBoardViewController.php b/src/controller/board/SprintBoardViewController.php index 76a741d..7b4f757 100755 --- a/src/controller/board/SprintBoardViewController.php +++ b/src/controller/board/SprintBoardViewController.php @@ -69,6 +69,13 @@ // TODO: Expand the checks here if we add the ability // to hide the Backlog column if (!$columns) { + $can_edit = PhabricatorPolicyFilter::hasCapability( + $viewer, + $project, + PhabricatorPolicyCapability::CAN_EDIT); + if (!$can_edit) { + return $this->noAccessDialog($project); + } switch ($request->getStr('initialize-type')) { case 'backlog-only': $unguarded = AphrontWriteGuard::beginScopedUnguardedWrites(); @@ -409,17 +416,22 @@ ->appendChild($board) ->addClass('project-board-wrapper'); - $nav = $this->buildIconNavView($project); - $nav->appendChild($header_box); - $nav->appendChild($board_box); + $nav = $this->getProfileMenu(); - return $this->buildApplicationPage( - $nav, - array( - 'title' => pht('%s Board', $project->getName()), - 'showFooter' => false, - 'pageObjects' => array($project->getPHID()), - )); + return $this->newPage() + ->setTitle(pht('%s Board', $project->getName())) + ->setPageObjectPHIDs(array($project->getPHID())) + ->setShowFooter(false) + ->setNavigation($nav) + ->addQuicksandConfig( + array( + 'boardConfig' => $behavior_config, + )) + ->appendChild( + array( + $header_box, + $board_box, + )); } private function buildSortMenu( diff --git a/src/engine/SprintProjectDetailsProfilePanel.php b/src/engine/SprintProjectDetailsProfilePanel.php new file mode 100644 index 0000000..a468e56 --- /dev/null +++ b/src/engine/SprintProjectDetailsProfilePanel.php @@ -0,0 +1,59 @@ +<?php + +final class SprintProjectDetailsProfilePanel + extends PhabricatorProfilePanel { + + const PANELKEY = 'sprint.details'; + + public function getPanelTypeName() { + return pht('Sprint Details'); + } + + private function getDefaultName() { + return pht('Sprint Details'); + } + + public function getDisplayName( + PhabricatorProfilePanelConfiguration $config) { + $name = $config->getPanelProperty('name'); + + if (strlen($name)) { + return $name; + } + + return $this->getDefaultName(); + } + + public function buildEditEngineFields( + PhabricatorProfilePanelConfiguration $config) { + return array( + id(new PhabricatorTextEditField()) + ->setKey('name') + ->setLabel(pht('Name')) + ->setPlaceholder($this->getDefaultName()) + ->setValue($config->getPanelProperty('name')), + ); + } + + protected function newNavigationMenuItems( + PhabricatorProfilePanelConfiguration $config) { + + $project = $config->getProfileObject(); + + $id = $project->getID(); + $picture = $project->getProfileImageURI(); + $name = $project->getName(); + + $href = "/project/sprint/profile/{$id}/"; + + $item = $this->newItem() + ->setHref($href) + ->setName($name) + ->setProfileImage($picture); + + return array( + $item, + ); + } + +} diff --git a/src/engine/SprintProjectProfilePanelEngine.php b/src/engine/SprintProjectProfilePanelEngine.php new file mode 100644 index 0000000..ff191c5 --- /dev/null +++ b/src/engine/SprintProjectProfilePanelEngine.php @@ -0,0 +1,52 @@ +<?php + +final class SprintProjectProfilePanelEngine + extends PhabricatorProfilePanelEngine { + + protected function getPanelURI($path) { + $project = $this->getProfileObject(); + $id = $project->getID(); + return "/project/{$id}/panel/{$path}"; + } + + protected function getBuiltinProfilePanels($object) { + $panels = array(); + + $panels[] = $this->newPanel() + ->setBuiltinKey(PhabricatorProject::PANEL_PROFILE) + ->setPanelKey(SprintProjectDetailsProfilePanel::PANELKEY); + + $panels[] = $this->newPanel() + ->setBuiltinKey(PhabricatorProject::PANEL_WORKBOARD) + ->setPanelKey(SprintProjectWorkboardProfilePanel::PANELKEY); + + $id = $object->getID(); + // TODO: This is temporary. + $uri = urisprintf( + '/maniphest/?statuses=open()&projects=%s#R', + $object->getPHID()); + + $panels[] = $this->newPanel() + ->setBuiltinKey('tasks') + ->setPanelKey(PhabricatorLinkProfilePanel::PANELKEY) + ->setPanelProperty('icon', 'maniphest') + ->setPanelProperty('name', pht('Open Tasks')) + ->setPanelProperty('uri', $uri); + + // TODO: This is temporary. + + $panels[] = $this->newPanel() + ->setBuiltinKey('feed') + ->setPanelKey(PhabricatorLinkProfilePanel::PANELKEY) + ->setPanelProperty('icon', 'feed') + ->setPanelProperty('name', pht('Feed')) + ->setPanelProperty('uri', "/project/feed/{$id}/"); + + $panels[] = $this->newPanel() + ->setBuiltinKey(PhabricatorProject::PANEL_MEMBERS) + ->setPanelKey(PhabricatorProjectMembersProfilePanel::PANELKEY); + + return $panels; + } + +} diff --git a/src/profilepanel/SprintProjectWorkboardProfilePanel.php b/src/profilepanel/SprintProjectWorkboardProfilePanel.php new file mode 100644 index 0000000..d1a8a1e --- /dev/null +++ b/src/profilepanel/SprintProjectWorkboardProfilePanel.php @@ -0,0 +1,74 @@ +<?php + +final class SprintProjectWorkboardProfilePanel + extends PhabricatorProfilePanel { + + const PANELKEY = 'sprint.workboard'; + + public function getPanelTypeName() { + return pht('Project Workboard'); + } + + private function getDefaultName() { + return pht('Workboard'); + } + + public function getDisplayName( + PhabricatorProfilePanelConfiguration $config) { + $name = $config->getPanelProperty('name'); + + if (strlen($name)) { + return $name; + } + + return $this->getDefaultName(); + } + + public function buildEditEngineFields( + PhabricatorProfilePanelConfiguration $config) { + return array( + id(new PhabricatorTextEditField()) + ->setKey('name') + ->setLabel(pht('Name')) + ->setPlaceholder($this->getDefaultName()) + ->setValue($config->getPanelProperty('name')), + ); + } + + protected function newNavigationMenuItems( + PhabricatorProfilePanelConfiguration $config) { + $viewer = $this->getViewer(); + + // Workboards are only available if Maniphest is installed. + $class = 'PhabricatorManiphestApplication'; + if (!PhabricatorApplication::isClassInstalledForViewer($class, $viewer)) { + return array(); + } + + $project = $config->getProfileObject(); + + $columns = id(new PhabricatorProjectColumnQuery()) + ->setViewer($viewer) + ->withProjectPHIDs(array($project->getPHID())) + ->execute(); + if ($columns) { + $icon = 'fa-columns'; + } else { + $icon = 'fa-columns grey'; + } + + $id = $project->getID(); + $href = "/project/sprint/board/{$id}/"; + $name = $this->getDisplayName($config); + + $item = $this->newItem() + ->setHref($href) + ->setName($name) + ->setIcon($icon); + + return array( + $item, + ); + } + +} -- To view, visit https://gerrit.wikimedia.org/r/264795 To unsubscribe, visit https://gerrit.wikimedia.org/r/settings Gerrit-MessageType: merged Gerrit-Change-Id: I94bec5bf20aca837ca742c2648c881cd6ed12b95 Gerrit-PatchSet: 1 Gerrit-Project: phabricator/extensions/Sprint Gerrit-Branch: master Gerrit-Owner: Christopher Johnson (WMDE) <christopher.john...@wikimedia.de> Gerrit-Reviewer: Christopher Johnson (WMDE) <christopher.john...@wikimedia.de> Gerrit-Reviewer: jenkins-bot <> _______________________________________________ MediaWiki-commits mailing list MediaWiki-commits@lists.wikimedia.org https://lists.wikimedia.org/mailman/listinfo/mediawiki-commits