1
0
Fork 0
mirror of https://we.phorge.it/source/phorge.git synced 2024-11-29 10:12:41 +01:00

Allow users to customize applicaiton tile sizes

Summary:
See discussion in D4438. Allows users to customize application tiles, and implements generally reasonable defaults so they hopefully won't.

Sizes are "invisible" (internal only, used to hide admin apps from non-admins), "hidden" (hide by default, show after clicking "Show More Applications"), "show" (show a small square tile) and "full" (show a full-width tile with subtitle).

Test Plan:
Default view for a non-admin:

{F29375}

Adjusted settings, hidden:

{F29373}

Adjusted settings, shown:

{F29374}

Reviewers: chad, btrahan

Reviewed By: chad

CC: aran

Differential Revision: https://secure.phabricator.com/D4439
This commit is contained in:
epriestley 2013-01-16 09:00:11 -08:00
parent fb9a1c38fb
commit fffa7ffb6c
8 changed files with 335 additions and 42 deletions

View file

@ -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',

View file

@ -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',

View file

@ -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 )-------------------------------------------------------- */

View file

@ -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);
foreach ($applications as $key => $application) {
$status[get_class($application)] = $application->loadStatus($user);
}
$views = array();
$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(
'<div '.
'id="'.phutil_escape_html($show_tiles_id).'"'.
'style="display: none;">');
Javelin::initBehavior('phabricator-home-reveal-tiles', array(
'tilesID' => $show_tiles_id,
'showID' => $show_item_id,
));
}
foreach ($tile_group as $group => $application_list) {
$tiles = array();
foreach ($application_list as $key => $application) {
$tile = id(new PhabricatorApplicationLaunchView())
->setApplication($application)
->setApplicationStatus(idx($status, $key, array()))
->setApplicationStatus(
idx($status, get_class($application), array()))
->setUser($user);
if ($group == PhabricatorApplication::GROUP_CORE) {
if ($tile_display == PhabricatorApplication::TILE_FULL) {
$tile->setFullWidth(true);
}
$views[] = $tile;
$tiles[] = $tile;
}
while (count($views) % 4) {
$views[] = id(new PhabricatorApplicationLaunchView());
if ($is_small_tiles) {
while (count($tiles) % 4) {
$tiles[] = id(new PhabricatorApplicationLaunchView());
}
$nav->addLabel($groups[$group]);
}
$nav->addCustomBlock(
phutil_render_tag(
'div',
array(
'class' => 'application-tile-group',
),
id(new AphrontNullView())->appendChild($views)->render()));
id(new AphrontNullView())->appendChild($tiles)->render()));
}
$is_hide = ($tile_display == PhabricatorApplication::TILE_HIDE);
if ($is_hide) {
$nav->addMenuItem($hide_item);
$nav->addCustomBlock('</div>');
}
}
$nav->addFilter(
'',
pht('Customize Applications...'),
'/settings/panel/home/');
$nav->addClass('phabricator-side-menu-home');
$nav->selectFilter(null);

View file

@ -0,0 +1,108 @@
<?php
final class PhabricatorSettingsPanelHomePreferences
extends PhabricatorSettingsPanel {
public function getPanelKey() {
return 'home';
}
public function getPanelName() {
return pht('Home Page');
}
public function getPanelGroup() {
return pht('Application Settings');
}
public function processRequest(AphrontRequest $request) {
$user = $request->getUser();
$preferences = $user->loadPreferences();
$apps = PhabricatorApplication::getAllInstalledApplications();
$pref_tiles = PhabricatorUserPreferences::PREFERENCE_APP_TILES;
$tiles = $preferences->getPreference($pref_tiles, array());
if ($request->isFormPost()) {
$values = $request->getArr('tile');
foreach ($apps as $app) {
$key = get_class($app);
$value = idx($values, $key);
switch ($value) {
case PhabricatorApplication::TILE_FULL:
case PhabricatorApplication::TILE_SHOW:
case PhabricatorApplication::TILE_HIDE:
$tiles[$key] = $value;
break;
default:
unset($tiles[$key]);
break;
}
}
$preferences->setPreference($pref_tiles, $tiles);
$preferences->save();
return id(new AphrontRedirectResponse())
->setURI($this->getPanelURI('?saved=true'));
}
$header = id(new PhabricatorHeaderView())
->setHeader(pht('Home Page Preferences'));
$form = id(new AphrontFormView())
->setFlexible(true)
->setUser($user);
$apps = msort($apps, 'getName');
foreach ($apps as $app) {
if (!$app->shouldAppearInLaunchView()) {
continue;
}
$default = $app->getDefaultTileDisplay($user);
if ($default == PhabricatorApplication::TILE_INVISIBLE) {
continue;
}
$default_name = PhabricatorApplication::getTileDisplayName($default);
$hide = PhabricatorApplication::TILE_HIDE;
$show = PhabricatorApplication::TILE_SHOW;
$full = PhabricatorApplication::TILE_FULL;
$key = get_class($app);
$form->appendChild(
id(new AphrontFormSelectControl())
->setLabel($app->getName())
->setName('tile['.$key.']')
->setOptions(
array(
$hide => PhabricatorApplication::getTileDisplayName($hide),
'default' => pht('Use Default (%s)', $default_name),
$show => PhabricatorApplication::getTileDisplayName($show),
$full => PhabricatorApplication::getTileDisplayName($full),
))
->setValue(idx($tiles, $key, 'default')));
}
$form
->appendChild(
id(new AphrontFormSubmitControl())
->setValue('Save Preferences'));
$error_view = null;
if ($request->getStr('saved') === 'true') {
$error_view = id(new AphrontErrorView())
->setTitle('Preferences Saved')
->setSeverity(AphrontErrorView::SEVERITY_NOTICE)
->setErrors(array('Your preferences have been saved.'));
}
return array(
$header,
$error_view,
$form,
);
}
}

View file

@ -20,6 +20,7 @@ final class PhabricatorUserPreferences extends PhabricatorUserDAO {
const PREFERENCE_DIFFUSION_SYMBOLS = 'diffusion-symbols';
const PREFERENCE_NAV_WIDTH = 'nav-width';
const PREFERENCE_APP_TILES = 'app-tiles';
protected $userPHID;
protected $preferences = array();

View file

@ -16,6 +16,33 @@ final class PhabricatorMenuItemView extends AphrontView {
private $sortOrder = 1.0;
private $icon;
private $selected;
private $sigils = array();
private $metadata;
private $id;
public function setID($id) {
$this->id = $id;
return $this;
}
public function setProperty($property) {
$this->property = $property;
return $this;
}
public function getProperty() {
return $this->property;
}
public function setMetadata($metadata) {
$this->metadata = $metadata;
return $this;
}
public function addSigil($sigil) {
$this->sigils[] = $sigil;
return $this;
}
public function setSelected($selected) {
$this->selected = $selected;
@ -125,12 +152,24 @@ final class PhabricatorMenuItemView extends AphrontView {
phutil_escape_html($this->name.$external));
}
$sigils = $this->sigils;
if ($this->workflow) {
$sigils[] = 'workflow';
}
if ($sigils) {
$sigils = implode(' ', $sigils);
} else {
$sigils = null;
}
return javelin_render_tag(
$this->href ? 'a' : 'div',
array(
'class' => implode(' ', $classes),
'href' => $this->href,
'sigil' => $this->workflow ? 'workflow' : null,
'sigil' => $sigils,
'meta' => $this->metadata,
'id' => $this->id,
),
$this->renderChildren().
$name);

View file

@ -0,0 +1,29 @@
/**
* @provides javelin-behavior-phabricator-home-reveal-tiles
* @requires javelin-behavior
* javelin-stratcom
* javelin-dom
* @javelin
*/
JX.behavior('phabricator-home-reveal-tiles', function(config) {
JX.Stratcom.listen(
'click',
'home-show-applications',
function(e) {
e.kill();
JX.DOM.show(JX.$(config.tilesID));
JX.DOM.hide(JX.$(config.showID));
});
JX.Stratcom.listen(
'click',
'home-hide-applications',
function(e) {
e.kill();
JX.DOM.hide(JX.$(config.tilesID));
JX.DOM.show(JX.$(config.showID));
});
});