diff --git a/scripts/celerity_mapper.php b/scripts/celerity_mapper.php index eb57ecc97e..fd24b0eaa4 100755 --- a/scripts/celerity_mapper.php +++ b/scripts/celerity_mapper.php @@ -57,6 +57,7 @@ $package_spec = array( 'phabricator-textareautils', 'phabricator-file-upload', 'javelin-behavior-global-drag-and-drop', + 'javelin-behavior-phabricator-home-reveal-tiles', ), 'core.pkg.css' => array( 'phabricator-core-css', diff --git a/src/__phutil_library_map__.php b/src/__phutil_library_map__.php index 7cb1d89ef7..8fecd377ae 100644 --- a/src/__phutil_library_map__.php +++ b/src/__phutil_library_map__.php @@ -1185,6 +1185,7 @@ phutil_register_library_map(array( 'PhabricatorSettingsPanelDisplayPreferences' => 'applications/settings/panel/PhabricatorSettingsPanelDisplayPreferences.php', 'PhabricatorSettingsPanelEmailAddresses' => 'applications/settings/panel/PhabricatorSettingsPanelEmailAddresses.php', 'PhabricatorSettingsPanelEmailPreferences' => 'applications/settings/panel/PhabricatorSettingsPanelEmailPreferences.php', + 'PhabricatorSettingsPanelHomePreferences' => 'applications/settings/panel/PhabricatorSettingsPanelHomePreferences.php', 'PhabricatorSettingsPanelLDAP' => 'applications/settings/panel/PhabricatorSettingsPanelLDAP.php', 'PhabricatorSettingsPanelOAuth' => 'applications/settings/panel/PhabricatorSettingsPanelOAuth.php', 'PhabricatorSettingsPanelPassword' => 'applications/settings/panel/PhabricatorSettingsPanelPassword.php', @@ -2525,6 +2526,7 @@ phutil_register_library_map(array( 'PhabricatorSettingsPanelDisplayPreferences' => 'PhabricatorSettingsPanel', 'PhabricatorSettingsPanelEmailAddresses' => 'PhabricatorSettingsPanel', 'PhabricatorSettingsPanelEmailPreferences' => 'PhabricatorSettingsPanel', + 'PhabricatorSettingsPanelHomePreferences' => 'PhabricatorSettingsPanel', 'PhabricatorSettingsPanelLDAP' => 'PhabricatorSettingsPanel', 'PhabricatorSettingsPanelOAuth' => 'PhabricatorSettingsPanel', 'PhabricatorSettingsPanelPassword' => 'PhabricatorSettingsPanel', diff --git a/src/applications/base/PhabricatorApplication.php b/src/applications/base/PhabricatorApplication.php index 68c1ed74ff..3f1a352f0b 100644 --- a/src/applications/base/PhabricatorApplication.php +++ b/src/applications/base/PhabricatorApplication.php @@ -18,6 +18,11 @@ abstract class PhabricatorApplication { const GROUP_DEVELOPER = 'developer'; const GROUP_MISC = 'misc'; + const TILE_INVISIBLE = 'invisible'; + const TILE_HIDE = 'hide'; + const TILE_SHOW = 'show'; + const TILE_FULL = 'full'; + public static function getApplicationGroups() { return array( self::GROUP_CORE => pht('Core Applications'), @@ -30,6 +35,17 @@ abstract class PhabricatorApplication { ); } + public static function getTileDisplayName($constant) { + $names = array( + self::TILE_INVISIBLE => pht('Invisible'), + self::TILE_HIDE => pht('Hidden'), + self::TILE_SHOW => pht('Show Small Tile'), + self::TILE_FULL => pht('Show Large Tile'), + ); + return idx($names, $constant); + } + + /* -( Application Information )-------------------------------------------- */ @@ -96,6 +112,25 @@ abstract class PhabricatorApplication { return array(); } + public function getDefaultTileDisplay(PhabricatorUser $user) { + switch ($this->getApplicationGroup()) { + case self::GROUP_CORE: + return self::TILE_FULL; + case self::GROUP_UTILITIES: + case self::GROUP_DEVELOPER: + return self::TILE_HIDE; + case self::GROUP_ADMIN: + if ($user->getIsAdmin()) { + return self::TILE_SHOW; + } else { + return self::TILE_INVISIBLE; + } + break; + default: + return self::TILE_SHOW; + } + } + /* -( URI Routing )-------------------------------------------------------- */ diff --git a/src/applications/directory/controller/PhabricatorDirectoryController.php b/src/applications/directory/controller/PhabricatorDirectoryController.php index 2e517a333d..81ca7225da 100644 --- a/src/applications/directory/controller/PhabricatorDirectoryController.php +++ b/src/applications/directory/controller/PhabricatorDirectoryController.php @@ -25,51 +25,129 @@ abstract class PhabricatorDirectoryController extends PhabricatorController { foreach ($applications as $key => $application) { if (!$application->shouldAppearInLaunchView()) { + // Remove hidden applications (usually internal stuff). + unset($applications[$key]); + } + $invisible = PhabricatorApplication::TILE_INVISIBLE; + if ($application->getDefaultTileDisplay($user) == $invisible) { + // Remove invisible applications (e.g., admin apps for non-admins). unset($applications[$key]); } } - $groups = PhabricatorApplication::getApplicationGroups(); - - $applications = msort($applications, 'getApplicationOrder'); - $applications = mgroup($applications, 'getApplicationGroup'); - $applications = array_select_keys($applications, array_keys($groups)); - - $view = array(); - foreach ($applications as $group => $application_list) { - $status = array(); - foreach ($application_list as $key => $application) { - $status[$key] = $application->loadStatus($user); - } - - $views = array(); - foreach ($application_list as $key => $application) { - $tile = id(new PhabricatorApplicationLaunchView()) - ->setApplication($application) - ->setApplicationStatus(idx($status, $key, array())) - ->setUser($user); - - if ($group == PhabricatorApplication::GROUP_CORE) { - $tile->setFullWidth(true); - } - - $views[] = $tile; - } - - while (count($views) % 4) { - $views[] = id(new PhabricatorApplicationLaunchView()); - } - - $nav->addLabel($groups[$group]); - $nav->addCustomBlock( - phutil_render_tag( - 'div', - array( - 'class' => 'application-tile-group', - ), - id(new AphrontNullView())->appendChild($views)->render())); + $status = array(); + foreach ($applications as $key => $application) { + $status[get_class($application)] = $application->loadStatus($user); } + $tile_groups = array(); + $prefs = $user->loadPreferences()->getPreference( + PhabricatorUserPreferences::PREFERENCE_APP_TILES, + array()); + foreach ($applications as $key => $application) { + $display = idx( + $prefs, + get_class($application), + $application->getDefaultTileDisplay($user)); + $tile_groups[$display][] = $application; + } + + $tile_groups = array_select_keys( + $tile_groups, + array( + PhabricatorApplication::TILE_FULL, + PhabricatorApplication::TILE_SHOW, + PhabricatorApplication::TILE_HIDE, + )); + + foreach ($tile_groups as $tile_display => $tile_group) { + if (!$tile_group) { + continue; + } + + $tile_group = msort($tile_group, 'getApplicationOrder'); + + $is_small_tiles = ($tile_display == PhabricatorApplication::TILE_SHOW) || + ($tile_display == PhabricatorApplication::TILE_HIDE); + + if ($is_small_tiles) { + $groups = PhabricatorApplication::getApplicationGroups(); + $tile_group = mgroup($tile_group, 'getApplicationGroup'); + $tile_group = array_select_keys($tile_group, array_keys($groups)); + } else { + $tile_group = array($tile_group); + } + + $is_hide = ($tile_display == PhabricatorApplication::TILE_HIDE); + if ($is_hide) { + $show_item_id = celerity_generate_unique_node_id(); + $show_tiles_id = celerity_generate_unique_node_id(); + + $show_item = id(new PhabricatorMenuItemView()) + ->setName(pht('Show More Applications')) + ->setHref('#') + ->addSigil('home-show-applications') + ->setID($show_item_id); + + $hide_item = id(new PhabricatorMenuItemView()) + ->setName(pht('Show Fewer Applications')) + ->setHref('#') + ->addSigil('home-hide-applications'); + + $nav->addMenuItem($show_item); + $nav->addCustomBlock( + '