diff --git a/src/applications/config/application/PhabricatorConfigApplication.php b/src/applications/config/application/PhabricatorConfigApplication.php --- a/src/applications/config/application/PhabricatorConfigApplication.php +++ b/src/applications/config/application/PhabricatorConfigApplication.php @@ -63,7 +63,7 @@ 'purge/' => 'PhabricatorConfigPurgeCacheController', ), 'module/' => array( - '(?P[^/]+)/' => 'PhabricatorConfigModuleController', + '(?:(?P[^/]+)/)?' => 'PhabricatorConfigModuleController', ), 'cluster/' => array( 'databases/' => 'PhabricatorConfigClusterDatabasesController', diff --git a/src/applications/config/controller/PhabricatorConfigController.php b/src/applications/config/controller/PhabricatorConfigController.php --- a/src/applications/config/controller/PhabricatorConfigController.php +++ b/src/applications/config/controller/PhabricatorConfigController.php @@ -42,13 +42,6 @@ pht('Repository Servers'), null, 'fa-code'); $nav->addFilter('cluster/search/', pht('Search Servers'), null, 'fa-search'); - $nav->addLabel(pht('Modules')); - - $modules = PhabricatorConfigModule::getAllModules(); - foreach ($modules as $key => $module) { - $nav->addFilter('module/'.$key.'/', - $module->getModuleName(), null, 'fa-puzzle-piece'); - } return $nav; } diff --git a/src/applications/config/controller/PhabricatorConfigModuleController.php b/src/applications/config/controller/PhabricatorConfigModuleController.php --- a/src/applications/config/controller/PhabricatorConfigModuleController.php +++ b/src/applications/config/controller/PhabricatorConfigModuleController.php @@ -8,6 +8,11 @@ $key = $request->getURIData('module'); $all_modules = PhabricatorConfigModule::getAllModules(); + + if (!strlen($key)) { + $key = head_key($all_modules); + } + if (empty($all_modules[$key])) { return new Aphront404Response(); } @@ -16,13 +21,27 @@ $content = $module->renderModuleStatus($request); $title = $module->getModuleName(); - $nav = $this->buildSideNavView(); - $nav->selectFilter('module/'.$key.'/'); + $nav = new AphrontSideNavFilterView(); + $nav->setBaseURI(new PhutilURI($this->getApplicationURI())); + + $modules_uri = $this->getApplicationURI('module/'); + + $modules = PhabricatorConfigModule::getAllModules(); + + foreach ($modules as $module_key => $module) { + $nav->newLink($module_key) + ->setName($module->getModuleName()) + ->setHref(urisprintf('%s%s/', $modules_uri, $module_key)) + ->setIcon('fa-puzzle-piece'); + } + + $nav->selectFilter($key); $header = $this->buildHeaderView($title); $view = $this->buildConfigBoxView($title, $content); $crumbs = $this->buildApplicationCrumbs() + ->addTextCrumb(pht('Extensions/Modules'), $modules_uri) ->addTextCrumb($title) ->setBorder(true);