mirror of
https://we.phorge.it/source/phorge.git
synced 2024-11-18 12:52:42 +01:00
Remove application small/hidden tiles
Summary: Ref T5176. This paves the way for the redesign by making the homepage editor thing a little more manageable/coherent. Not perfect, but we can clean it up a bit after the new design. Test Plan: Home page: {F162093} New "Pinned Applications" settings panel (this supports drag-and-drop to reorder): {F162094} Pin an app: {F162095} Unpin an app: {F162096} Reviewers: btrahan, chad Reviewed By: chad Subscribers: epriestley Maniphest Tasks: T5176 Differential Revision: https://secure.phabricator.com/D9332
This commit is contained in:
parent
09a3506821
commit
24eacaa032
7 changed files with 263 additions and 289 deletions
|
@ -100,7 +100,6 @@ return array(
|
||||||
'rsrc/css/application/releeph/releeph-request-differential-create-dialog.css' => '8d8b92cd',
|
'rsrc/css/application/releeph/releeph-request-differential-create-dialog.css' => '8d8b92cd',
|
||||||
'rsrc/css/application/releeph/releeph-request-typeahead.css' => '667a48ae',
|
'rsrc/css/application/releeph/releeph-request-typeahead.css' => '667a48ae',
|
||||||
'rsrc/css/application/search/search-results.css' => 'f240504c',
|
'rsrc/css/application/search/search-results.css' => 'f240504c',
|
||||||
'rsrc/css/application/settings/settings.css' => 'ea8f5915',
|
|
||||||
'rsrc/css/application/slowvote/slowvote.css' => '266df6a1',
|
'rsrc/css/application/slowvote/slowvote.css' => '266df6a1',
|
||||||
'rsrc/css/application/subscriptions/subscribers-list.css' => '5bb30c78',
|
'rsrc/css/application/subscriptions/subscribers-list.css' => '5bb30c78',
|
||||||
'rsrc/css/application/tokens/tokens.css' => '3d0f239e',
|
'rsrc/css/application/tokens/tokens.css' => '3d0f239e',
|
||||||
|
@ -468,6 +467,7 @@ return array(
|
||||||
'rsrc/js/core/behavior-phabricator-remarkup-assist.js' => 'c021950a',
|
'rsrc/js/core/behavior-phabricator-remarkup-assist.js' => 'c021950a',
|
||||||
'rsrc/js/core/behavior-refresh-csrf.js' => '7814b593',
|
'rsrc/js/core/behavior-refresh-csrf.js' => '7814b593',
|
||||||
'rsrc/js/core/behavior-remarkup-preview.js' => 'f7379f45',
|
'rsrc/js/core/behavior-remarkup-preview.js' => 'f7379f45',
|
||||||
|
'rsrc/js/core/behavior-reorder-applications.js' => 'a8e3795d',
|
||||||
'rsrc/js/core/behavior-reveal-content.js' => '8f24abfc',
|
'rsrc/js/core/behavior-reveal-content.js' => '8f24abfc',
|
||||||
'rsrc/js/core/behavior-search-typeahead.js' => '86549ee3',
|
'rsrc/js/core/behavior-search-typeahead.js' => '86549ee3',
|
||||||
'rsrc/js/core/behavior-select-on-click.js' => '0e34ca02',
|
'rsrc/js/core/behavior-select-on-click.js' => '0e34ca02',
|
||||||
|
@ -629,6 +629,7 @@ return array(
|
||||||
'javelin-behavior-releeph-request-state-change' => 'd259e7c9',
|
'javelin-behavior-releeph-request-state-change' => 'd259e7c9',
|
||||||
'javelin-behavior-releeph-request-typeahead' => 'cd9e7094',
|
'javelin-behavior-releeph-request-typeahead' => 'cd9e7094',
|
||||||
'javelin-behavior-remarkup-preview' => 'f7379f45',
|
'javelin-behavior-remarkup-preview' => 'f7379f45',
|
||||||
|
'javelin-behavior-reorder-applications' => 'a8e3795d',
|
||||||
'javelin-behavior-repository-crossreference' => '8ab282be',
|
'javelin-behavior-repository-crossreference' => '8ab282be',
|
||||||
'javelin-behavior-search-reorder-queries' => '37871df4',
|
'javelin-behavior-search-reorder-queries' => '37871df4',
|
||||||
'javelin-behavior-select-on-click' => '0e34ca02',
|
'javelin-behavior-select-on-click' => '0e34ca02',
|
||||||
|
@ -720,7 +721,6 @@ return array(
|
||||||
'phabricator-project-tag-css' => '095c9404',
|
'phabricator-project-tag-css' => '095c9404',
|
||||||
'phabricator-remarkup-css' => '80c3a48c',
|
'phabricator-remarkup-css' => '80c3a48c',
|
||||||
'phabricator-search-results-css' => 'f240504c',
|
'phabricator-search-results-css' => 'f240504c',
|
||||||
'phabricator-settings-css' => 'ea8f5915',
|
|
||||||
'phabricator-shaped-request' => '7cbe244b',
|
'phabricator-shaped-request' => '7cbe244b',
|
||||||
'phabricator-side-menu-view-css' => 'c1986b85',
|
'phabricator-side-menu-view-css' => 'c1986b85',
|
||||||
'phabricator-slowvote-css' => '266df6a1',
|
'phabricator-slowvote-css' => '266df6a1',
|
||||||
|
@ -1612,6 +1612,14 @@ return array(
|
||||||
1 => 'javelin-dom',
|
1 => 'javelin-dom',
|
||||||
2 => 'javelin-stratcom',
|
2 => 'javelin-stratcom',
|
||||||
),
|
),
|
||||||
|
'a8e3795d' =>
|
||||||
|
array(
|
||||||
|
0 => 'javelin-behavior',
|
||||||
|
1 => 'javelin-stratcom',
|
||||||
|
2 => 'javelin-workflow',
|
||||||
|
3 => 'javelin-dom',
|
||||||
|
4 => 'phabricator-draggable-list',
|
||||||
|
),
|
||||||
'a9aaba0c' =>
|
'a9aaba0c' =>
|
||||||
array(
|
array(
|
||||||
0 => 'javelin-behavior',
|
0 => 'javelin-behavior',
|
||||||
|
|
|
@ -25,13 +25,10 @@ abstract class PhabricatorHomeController extends PhabricatorController {
|
||||||
->setViewer($user)
|
->setViewer($user)
|
||||||
->withInstalled(true)
|
->withInstalled(true)
|
||||||
->withUnlisted(false)
|
->withUnlisted(false)
|
||||||
|
->withLaunchable(true)
|
||||||
->execute();
|
->execute();
|
||||||
|
|
||||||
foreach ($applications as $key => $application) {
|
foreach ($applications as $key => $application) {
|
||||||
if (!$application->shouldAppearInLaunchView()) {
|
|
||||||
// Remove hidden applications (usually internal stuff).
|
|
||||||
unset($applications[$key]);
|
|
||||||
}
|
|
||||||
$invisible = PhabricatorApplication::TILE_INVISIBLE;
|
$invisible = PhabricatorApplication::TILE_INVISIBLE;
|
||||||
if ($application->getDefaultTileDisplay($user) == $invisible) {
|
if ($application->getDefaultTileDisplay($user) == $invisible) {
|
||||||
// Remove invisible applications (e.g., admin apps for non-admins).
|
// Remove invisible applications (e.g., admin apps for non-admins).
|
||||||
|
@ -39,115 +36,45 @@ abstract class PhabricatorHomeController extends PhabricatorController {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
$status = array();
|
$pinned = $user->loadPreferences()->getPinnedApplications(
|
||||||
foreach ($applications as $key => $application) {
|
$applications,
|
||||||
$status[get_class($application)] = $application->loadStatus($user);
|
$user);
|
||||||
}
|
|
||||||
|
|
||||||
$tile_groups = array();
|
// Put "Applications" at the bottom.
|
||||||
$prefs = $user->loadPreferences()->getPreference(
|
$meta_app = 'PhabricatorApplicationApplications';
|
||||||
PhabricatorUserPreferences::PREFERENCE_APP_TILES,
|
$pinned = array_fuse($pinned);
|
||||||
array());
|
unset($pinned[$meta_app]);
|
||||||
foreach ($applications as $key => $application) {
|
$pinned[$meta_app] = $meta_app;
|
||||||
$display = idx(
|
|
||||||
$prefs,
|
|
||||||
get_class($application),
|
|
||||||
$application->getDefaultTileDisplay($user));
|
|
||||||
$tile_groups[$display][] = $application;
|
|
||||||
}
|
|
||||||
|
|
||||||
$tile_groups = array_select_keys(
|
$tiles = array();
|
||||||
$tile_groups,
|
foreach ($pinned as $pinned_application) {
|
||||||
array(
|
if (empty($applications[$pinned_application])) {
|
||||||
PhabricatorApplication::TILE_FULL,
|
|
||||||
PhabricatorApplication::TILE_SHOW,
|
|
||||||
PhabricatorApplication::TILE_HIDE,
|
|
||||||
));
|
|
||||||
|
|
||||||
foreach ($tile_groups as $tile_display => $tile_group) {
|
|
||||||
if (!$tile_group) {
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
$is_small_tiles = ($tile_display == PhabricatorApplication::TILE_SHOW) ||
|
$application = $applications[$pinned_application];
|
||||||
($tile_display == PhabricatorApplication::TILE_HIDE);
|
|
||||||
|
|
||||||
if ($is_small_tiles) {
|
$tile = id(new PhabricatorApplicationLaunchView())
|
||||||
$groups = PhabricatorApplication::getApplicationGroups();
|
->setApplication($application)
|
||||||
$tile_group = mgroup($tile_group, 'getApplicationGroup');
|
->setApplicationStatus($application->loadStatus($user))
|
||||||
$tile_group = array_select_keys($tile_group, array_keys($groups));
|
->setUser($user);
|
||||||
} else {
|
|
||||||
$tile_group = array($tile_group);
|
|
||||||
}
|
|
||||||
|
|
||||||
$is_hide = ($tile_display == PhabricatorApplication::TILE_HIDE);
|
$tiles[] = $tile;
|
||||||
if ($is_hide) {
|
|
||||||
$show_item_id = celerity_generate_unique_node_id();
|
|
||||||
$hide_item_id = celerity_generate_unique_node_id();
|
|
||||||
|
|
||||||
$show_item = id(new PHUIListItemView())
|
|
||||||
->setName(pht('Show More Applications'))
|
|
||||||
->setHref('#')
|
|
||||||
->addSigil('reveal-content')
|
|
||||||
->setID($show_item_id);
|
|
||||||
|
|
||||||
$hide_item = id(new PHUIListItemView())
|
|
||||||
->setName(pht('Show Fewer Applications'))
|
|
||||||
->setHref('#')
|
|
||||||
->setStyle('display: none')
|
|
||||||
->setID($hide_item_id)
|
|
||||||
->addSigil('reveal-content');
|
|
||||||
|
|
||||||
$nav->addMenuItem($show_item);
|
|
||||||
$tile_ids = array($hide_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, get_class($application), array()))
|
|
||||||
->setUser($user);
|
|
||||||
|
|
||||||
$tiles[] = $tile;
|
|
||||||
}
|
|
||||||
|
|
||||||
$group_id = celerity_generate_unique_node_id();
|
|
||||||
$tile_ids[] = $group_id;
|
|
||||||
$nav->addCustomBlock(
|
|
||||||
phutil_tag(
|
|
||||||
'div',
|
|
||||||
array(
|
|
||||||
'class' => 'application-tile-group',
|
|
||||||
'id' => $group_id,
|
|
||||||
'style' => ($is_hide ? 'display: none' : null),
|
|
||||||
),
|
|
||||||
mpull($tiles, 'render')));
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($is_hide) {
|
|
||||||
Javelin::initBehavior('phabricator-reveal-content');
|
|
||||||
|
|
||||||
$show_item->setMetadata(
|
|
||||||
array(
|
|
||||||
'showIDs' => $tile_ids,
|
|
||||||
'hideIDs' => array($show_item_id),
|
|
||||||
));
|
|
||||||
$hide_item->setMetadata(
|
|
||||||
array(
|
|
||||||
'showIDs' => array($show_item_id),
|
|
||||||
'hideIDs' => $tile_ids,
|
|
||||||
));
|
|
||||||
$nav->addMenuItem($hide_item);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$nav->addCustomBlock(
|
||||||
|
phutil_tag(
|
||||||
|
'div',
|
||||||
|
array(
|
||||||
|
'class' => 'application-tile-group',
|
||||||
|
),
|
||||||
|
$tiles));
|
||||||
|
|
||||||
$nav->addFilter(
|
$nav->addFilter(
|
||||||
'',
|
'',
|
||||||
pht('Customize Applications...'),
|
pht('Customize Applications...'),
|
||||||
'/settings/panel/home/');
|
'/settings/panel/home/');
|
||||||
|
|
||||||
$nav->addClass('phabricator-side-menu-home');
|
$nav->addClass('phabricator-side-menu-home');
|
||||||
$nav->selectFilter(null);
|
$nav->selectFilter(null);
|
||||||
|
|
||||||
|
|
|
@ -19,194 +19,179 @@ final class PhabricatorSettingsPanelHomePreferences
|
||||||
$user = $request->getUser();
|
$user = $request->getUser();
|
||||||
$preferences = $user->loadPreferences();
|
$preferences = $user->loadPreferences();
|
||||||
|
|
||||||
require_celerity_resource('phabricator-settings-css');
|
|
||||||
|
|
||||||
$apps = id(new PhabricatorApplicationQuery())
|
$apps = id(new PhabricatorApplicationQuery())
|
||||||
->setViewer($user)
|
->setViewer($user)
|
||||||
->withInstalled(true)
|
->withInstalled(true)
|
||||||
->withUnlisted(false)
|
->withUnlisted(false)
|
||||||
|
->withLaunchable(true)
|
||||||
->execute();
|
->execute();
|
||||||
|
|
||||||
$pref_tiles = PhabricatorUserPreferences::PREFERENCE_APP_TILES;
|
$pinned = $preferences->getPinnedApplications($apps, $user);
|
||||||
$tiles = $preferences->getPreference($pref_tiles, array());
|
|
||||||
|
|
||||||
if ($request->isFormPost()) {
|
$app_list = array();
|
||||||
$values = $request->getArr('tile');
|
foreach ($pinned as $app) {
|
||||||
|
if (isset($apps[$app])) {
|
||||||
|
$app_list[$app] = $apps[$app];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($request->getBool('add')) {
|
||||||
|
$options = array();
|
||||||
foreach ($apps as $app) {
|
foreach ($apps as $app) {
|
||||||
$key = get_class($app);
|
$options[get_class($app)] = $app->getName();
|
||||||
$value = idx($values, $key);
|
}
|
||||||
switch ($value) {
|
asort($options);
|
||||||
case PhabricatorApplication::TILE_FULL:
|
|
||||||
case PhabricatorApplication::TILE_SHOW:
|
unset($options['PhabricatorApplicationApplications']);
|
||||||
case PhabricatorApplication::TILE_HIDE:
|
|
||||||
$tiles[$key] = $value;
|
if ($request->isFormPost()) {
|
||||||
break;
|
$pin = $request->getStr('pin');
|
||||||
default:
|
if (isset($options[$pin]) && !in_array($pin, $pinned)) {
|
||||||
unset($tiles[$key]);
|
$pinned[] = $pin;
|
||||||
break;
|
$preferences->setPreference(
|
||||||
|
PhabricatorUserPreferences::PREFERENCE_APP_PINNED,
|
||||||
|
$pinned);
|
||||||
|
$preferences->save();
|
||||||
|
|
||||||
|
return id(new AphrontRedirectResponse())
|
||||||
|
->setURI($this->getPanelURI());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
$preferences->setPreference($pref_tiles, $tiles);
|
|
||||||
|
$options_control = id(new AphrontFormSelectControl())
|
||||||
|
->setName('pin')
|
||||||
|
->setLabel(pht('Application'))
|
||||||
|
->setOptions($options)
|
||||||
|
->setDisabledOptions(array_keys($app_list));
|
||||||
|
|
||||||
|
$form = id(new AphrontFormView())
|
||||||
|
->setUser($user)
|
||||||
|
->addHiddenInput('add', 'true')
|
||||||
|
->appendRemarkupInstructions(
|
||||||
|
pht('Choose an application to pin to your home page.'))
|
||||||
|
->appendChild($options_control);
|
||||||
|
|
||||||
|
$dialog = id(new AphrontDialogView())
|
||||||
|
->setUser($user)
|
||||||
|
->setWidth(AphrontDialogView::WIDTH_FORM)
|
||||||
|
->setTitle(pht('Pin Application'))
|
||||||
|
->appendChild($form->buildLayoutView())
|
||||||
|
->addSubmitButton(pht('Pin Application'))
|
||||||
|
->addCancelButton($this->getPanelURI());
|
||||||
|
|
||||||
|
return id(new AphrontDialogResponse())->setDialog($dialog);
|
||||||
|
}
|
||||||
|
|
||||||
|
$unpin = $request->getStr('unpin');
|
||||||
|
if ($unpin) {
|
||||||
|
$app = idx($apps, $unpin);
|
||||||
|
if ($app) {
|
||||||
|
if ($request->isFormPost()) {
|
||||||
|
$pinned = array_diff($pinned, array($unpin));
|
||||||
|
$preferences->setPreference(
|
||||||
|
PhabricatorUserPreferences::PREFERENCE_APP_PINNED,
|
||||||
|
$pinned);
|
||||||
|
$preferences->save();
|
||||||
|
|
||||||
|
return id(new AphrontRedirectResponse())
|
||||||
|
->setURI($this->getPanelURI());
|
||||||
|
}
|
||||||
|
|
||||||
|
$dialog = id(new AphrontDialogView())
|
||||||
|
->setUser($user)
|
||||||
|
->setTitle(pht('Unpin Application'))
|
||||||
|
->appendParagraph(
|
||||||
|
pht(
|
||||||
|
'Unpin the %s application from your home page?',
|
||||||
|
phutil_tag('strong', array(), $app->getName())))
|
||||||
|
->addSubmitButton(pht('Unpin Application'))
|
||||||
|
->addCanceLButton($this->getPanelURI());
|
||||||
|
|
||||||
|
return id(new AphrontDialogResponse())->setDialog($dialog);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$order = $request->getStrList('order');
|
||||||
|
if ($order && $request->validateCSRF()) {
|
||||||
|
$preferences->setPreference(
|
||||||
|
PhabricatorUserPreferences::PREFERENCE_APP_PINNED,
|
||||||
|
$order);
|
||||||
$preferences->save();
|
$preferences->save();
|
||||||
|
|
||||||
return id(new AphrontRedirectResponse())
|
return id(new AphrontRedirectResponse())
|
||||||
->setURI($this->getPanelURI('?saved=true'));
|
->setURI($this->getPanelURI());
|
||||||
}
|
}
|
||||||
|
|
||||||
$form = id(new AphrontFormView())
|
$list_id = celerity_generate_unique_node_id();
|
||||||
->setUser($user);
|
|
||||||
|
|
||||||
$group_map = PhabricatorApplication::getApplicationGroups();
|
$list = id(new PHUIObjectItemListView())
|
||||||
|
->setUser($user)
|
||||||
|
->setID($list_id)
|
||||||
|
->setFlush(true);
|
||||||
|
|
||||||
$output = array();
|
Javelin::initBehavior(
|
||||||
|
'reorder-applications',
|
||||||
|
array(
|
||||||
|
'listID' => $list_id,
|
||||||
|
'panelURI' => $this->getPanelURI(),
|
||||||
|
));
|
||||||
|
|
||||||
$app_groups = mgroup($apps, 'getApplicationGroup');
|
foreach ($app_list as $key => $application) {
|
||||||
$app_groups = array_select_keys($app_groups, array_keys($group_map));
|
if ($key == 'PhabricatorApplicationApplications') {
|
||||||
|
|
||||||
foreach ($app_groups as $group => $apps) {
|
|
||||||
$group_name = $group_map[$group];
|
|
||||||
$rows = array();
|
|
||||||
|
|
||||||
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);
|
|
||||||
|
|
||||||
$default_radio_button_status =
|
|
||||||
(idx($tiles, $key, 'default') == 'default') ? 'checked' : null;
|
|
||||||
|
|
||||||
$hide_radio_button_status =
|
|
||||||
(idx($tiles, $key, 'default') == $hide) ? 'checked' : null;
|
|
||||||
|
|
||||||
$show_radio_button_status =
|
|
||||||
(idx($tiles, $key, 'default') == $show) ? 'checked' : null;
|
|
||||||
|
|
||||||
$full_radio_button_status =
|
|
||||||
(idx($tiles, $key, 'default') == $full) ? 'checked' : null;
|
|
||||||
|
|
||||||
|
|
||||||
$default_radio_button = phutil_tag(
|
|
||||||
'input',
|
|
||||||
array(
|
|
||||||
'type' => 'radio',
|
|
||||||
'name' => 'tile['.$key.']',
|
|
||||||
'value' => 'default',
|
|
||||||
'checked' => $default_radio_button_status,
|
|
||||||
));
|
|
||||||
|
|
||||||
$hide_radio_button = phutil_tag(
|
|
||||||
'input',
|
|
||||||
array(
|
|
||||||
'type' => 'radio',
|
|
||||||
'name' => 'tile['.$key.']',
|
|
||||||
'value' => $hide,
|
|
||||||
'checked' => $hide_radio_button_status,
|
|
||||||
));
|
|
||||||
|
|
||||||
$show_radio_button = phutil_tag(
|
|
||||||
'input',
|
|
||||||
array(
|
|
||||||
'type' => 'radio',
|
|
||||||
'name' => 'tile['.$key.']',
|
|
||||||
'value' => $show,
|
|
||||||
'checked' => $show_radio_button_status,
|
|
||||||
));
|
|
||||||
|
|
||||||
$full_radio_button = phutil_tag(
|
|
||||||
'input',
|
|
||||||
array(
|
|
||||||
'type' => 'radio',
|
|
||||||
'name' => 'tile['.$key.']',
|
|
||||||
'value' => $full,
|
|
||||||
'checked' => $full_radio_button_status,
|
|
||||||
));
|
|
||||||
|
|
||||||
$desc = $app->getShortDescription();
|
|
||||||
$app_column = hsprintf(
|
|
||||||
"<strong>%s</strong><br/ >%s, <em>Default: %s</em>",
|
|
||||||
$app->getName(), $desc, $default_name);
|
|
||||||
|
|
||||||
$rows[] = array(
|
|
||||||
$app_column,
|
|
||||||
$default_radio_button,
|
|
||||||
$hide_radio_button,
|
|
||||||
$show_radio_button,
|
|
||||||
$full_radio_button,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (empty($rows)) {
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
$table = new AphrontTableView($rows);
|
$icon = $application->getIconName();
|
||||||
|
if (!$icon) {
|
||||||
|
$icon = 'application';
|
||||||
|
}
|
||||||
|
|
||||||
$table
|
$icon_view = javelin_tag(
|
||||||
->setClassName('phabricator-settings-homepagetable')
|
'span',
|
||||||
->setHeaders(
|
array(
|
||||||
array(
|
'class' => 'phui-icon-view '.
|
||||||
pht('Applications'),
|
'sprite-apps-large apps-'.$icon.'-dark-large',
|
||||||
pht('Default'),
|
'aural' => false,
|
||||||
pht('Hidden'),
|
),
|
||||||
pht('Small'),
|
'');
|
||||||
pht('Large'),
|
|
||||||
))
|
|
||||||
->setColumnClasses(
|
|
||||||
array(
|
|
||||||
'',
|
|
||||||
'fixed',
|
|
||||||
'fixed',
|
|
||||||
'fixed',
|
|
||||||
'fixed',
|
|
||||||
));
|
|
||||||
|
|
||||||
|
$item = id(new PHUIObjectItemView())
|
||||||
|
->setHeader($application->getName())
|
||||||
|
->setImageIcon($icon_view)
|
||||||
|
->addAttribute($application->getShortDescription())
|
||||||
|
->setGrippable(true);
|
||||||
|
|
||||||
$panel = id(new PHUIObjectBoxView())
|
$item->addAction(
|
||||||
->setHeaderText($group_name)
|
id(new PHUIListItemView())
|
||||||
->appendChild($table);
|
->setIcon('fa-times')
|
||||||
|
->setHref($this->getPanelURI().'?unpin='.$key)
|
||||||
|
->setWorkflow(true));
|
||||||
|
|
||||||
$output[] = $panel;
|
$item->addSigil('pinned-application');
|
||||||
}
|
$item->setMetadata(
|
||||||
|
array(
|
||||||
|
'applicationClass' => $key,
|
||||||
|
));
|
||||||
|
|
||||||
$save_button =
|
$list->addItem($item);
|
||||||
id(new AphrontFormSubmitControl())
|
|
||||||
->setValue(pht('Save Preferences'));
|
|
||||||
|
|
||||||
$output[] = id(new PHUIBoxView())
|
|
||||||
->addPadding(PHUI::PADDING_LARGE)
|
|
||||||
->addClass('phabricator-settings-homepagetable-button')
|
|
||||||
->appendChild($save_button);
|
|
||||||
|
|
||||||
$form->appendChild($output);
|
|
||||||
|
|
||||||
$error_view = null;
|
|
||||||
if ($request->getStr('saved') === 'true') {
|
|
||||||
$error_view = id(new AphrontErrorView())
|
|
||||||
->setTitle(pht('Preferences Saved'))
|
|
||||||
->setSeverity(AphrontErrorView::SEVERITY_NOTICE)
|
|
||||||
->setErrors(array(pht('Your preferences have been saved.')));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
$header = id(new PHUIHeaderView())
|
$header = id(new PHUIHeaderView())
|
||||||
->setHeader(pht('Home Page Preferences'));
|
->setHeader(pht('Pinned Applications'))
|
||||||
|
->addActionLink(
|
||||||
|
id(new PHUIButtonView())
|
||||||
|
->setTag('a')
|
||||||
|
->setText(pht('Pin Application'))
|
||||||
|
->setHref($this->getPanelURI().'?add=true')
|
||||||
|
->setWorkflow(true)
|
||||||
|
->setIcon(
|
||||||
|
id(new PHUIIconView())
|
||||||
|
->setIconFont('fa-thumb-tack')));
|
||||||
|
|
||||||
$form = id(new PHUIBoxView())
|
$box = id(new PHUIObjectBoxView())
|
||||||
->addClass('phabricator-settings-homepagetable-wrap')
|
->setHeader($header)
|
||||||
->appendChild($form);
|
->appendChild($list);
|
||||||
|
|
||||||
return array($header, $error_view, $form);
|
return $box;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -24,6 +24,7 @@ final class PhabricatorUserPreferences extends PhabricatorUserDAO {
|
||||||
const PREFERENCE_NAV_COLLAPSED = 'nav-collapsed';
|
const PREFERENCE_NAV_COLLAPSED = 'nav-collapsed';
|
||||||
const PREFERENCE_NAV_WIDTH = 'nav-width';
|
const PREFERENCE_NAV_WIDTH = 'nav-width';
|
||||||
const PREFERENCE_APP_TILES = 'app-tiles';
|
const PREFERENCE_APP_TILES = 'app-tiles';
|
||||||
|
const PREFERENCE_APP_PINNED = 'app-pinned';
|
||||||
|
|
||||||
const PREFERENCE_DIFF_FILETREE = 'diff-filetree';
|
const PREFERENCE_DIFF_FILETREE = 'diff-filetree';
|
||||||
|
|
||||||
|
@ -55,4 +56,31 @@ final class PhabricatorUserPreferences extends PhabricatorUserDAO {
|
||||||
return $this;
|
return $this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function getPinnedApplications(array $apps, PhabricatorUser $viewer) {
|
||||||
|
$pref_pinned = PhabricatorUserPreferences::PREFERENCE_APP_PINNED;
|
||||||
|
$pinned = $this->getPreference($pref_pinned);
|
||||||
|
|
||||||
|
if ($pinned) {
|
||||||
|
return $pinned;
|
||||||
|
}
|
||||||
|
|
||||||
|
$pref_tiles = PhabricatorUserPreferences::PREFERENCE_APP_TILES;
|
||||||
|
$tiles = $this->getPreference($pref_tiles, array());
|
||||||
|
|
||||||
|
$large = array();
|
||||||
|
foreach ($apps as $app) {
|
||||||
|
$tile = $app->getDefaultTileDisplay($viewer);
|
||||||
|
|
||||||
|
if (isset($tiles[get_class($app)])) {
|
||||||
|
$tile = $tiles[get_class($app)];
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($tile == PhabricatorApplication::TILE_FULL) {
|
||||||
|
$large[] = get_class($app);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return $large;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,6 +7,7 @@ final class AphrontFormSelectControl extends AphrontFormControl {
|
||||||
}
|
}
|
||||||
|
|
||||||
private $options;
|
private $options;
|
||||||
|
private $disabledOptions = array();
|
||||||
|
|
||||||
public function setOptions(array $options) {
|
public function setOptions(array $options) {
|
||||||
$this->options = $options;
|
$this->options = $options;
|
||||||
|
@ -17,6 +18,11 @@ final class AphrontFormSelectControl extends AphrontFormControl {
|
||||||
return $this->options;
|
return $this->options;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function setDisabledOptions(array $disabled) {
|
||||||
|
$this->disabledOptions = $disabled;
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
protected function renderInput() {
|
protected function renderInput() {
|
||||||
return self::renderSelectTag(
|
return self::renderSelectTag(
|
||||||
$this->getValue(),
|
$this->getValue(),
|
||||||
|
@ -25,15 +31,17 @@ final class AphrontFormSelectControl extends AphrontFormControl {
|
||||||
'name' => $this->getName(),
|
'name' => $this->getName(),
|
||||||
'disabled' => $this->getDisabled() ? 'disabled' : null,
|
'disabled' => $this->getDisabled() ? 'disabled' : null,
|
||||||
'id' => $this->getID(),
|
'id' => $this->getID(),
|
||||||
));
|
),
|
||||||
|
$this->disabledOptions);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static function renderSelectTag(
|
public static function renderSelectTag(
|
||||||
$selected,
|
$selected,
|
||||||
array $options,
|
array $options,
|
||||||
array $attrs = array()) {
|
array $attrs = array(),
|
||||||
|
array $disabled = array()) {
|
||||||
|
|
||||||
$option_tags = self::renderOptions($selected, $options);
|
$option_tags = self::renderOptions($selected, $options, $disabled);
|
||||||
|
|
||||||
return javelin_tag(
|
return javelin_tag(
|
||||||
'select',
|
'select',
|
||||||
|
@ -41,7 +49,12 @@ final class AphrontFormSelectControl extends AphrontFormControl {
|
||||||
$option_tags);
|
$option_tags);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static function renderOptions($selected, array $options) {
|
private static function renderOptions(
|
||||||
|
$selected,
|
||||||
|
array $options,
|
||||||
|
array $disabled = array()) {
|
||||||
|
$disabled = array_fuse($disabled);
|
||||||
|
|
||||||
$tags = array();
|
$tags = array();
|
||||||
foreach ($options as $value => $thing) {
|
foreach ($options as $value => $thing) {
|
||||||
if (is_array($thing)) {
|
if (is_array($thing)) {
|
||||||
|
@ -57,6 +70,7 @@ final class AphrontFormSelectControl extends AphrontFormControl {
|
||||||
array(
|
array(
|
||||||
'selected' => ($value == $selected) ? 'selected' : null,
|
'selected' => ($value == $selected) ? 'selected' : null,
|
||||||
'value' => $value,
|
'value' => $value,
|
||||||
|
'disabled' => isset($disabled[$value]) ? 'disabled' : null,
|
||||||
),
|
),
|
||||||
$thing);
|
$thing);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,25 +0,0 @@
|
||||||
/**
|
|
||||||
* @provides phabricator-settings-css
|
|
||||||
*/
|
|
||||||
|
|
||||||
.phabricator-settings-homepagetable .fixed {
|
|
||||||
width: 48px;
|
|
||||||
text-align: center;
|
|
||||||
}
|
|
||||||
|
|
||||||
.phabricator-settings-homepagetable td em {
|
|
||||||
color: {$lightgreytext};
|
|
||||||
}
|
|
||||||
|
|
||||||
.phabricator-settings-homepagetable-button .aphront-form-input {
|
|
||||||
margin: 0;
|
|
||||||
width: auto;
|
|
||||||
}
|
|
||||||
|
|
||||||
.phabricator-settings-homepagetable-button .aphront-form-control {
|
|
||||||
padding: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
.phabricator-settings-homepagetable-wrap .phui-form-view {
|
|
||||||
padding: 0;
|
|
||||||
}
|
|
37
webroot/rsrc/js/core/behavior-reorder-applications.js
Normal file
37
webroot/rsrc/js/core/behavior-reorder-applications.js
Normal file
|
@ -0,0 +1,37 @@
|
||||||
|
/**
|
||||||
|
* @provides javelin-behavior-reorder-applications
|
||||||
|
* @requires javelin-behavior
|
||||||
|
* javelin-stratcom
|
||||||
|
* javelin-workflow
|
||||||
|
* javelin-dom
|
||||||
|
* phabricator-draggable-list
|
||||||
|
*/
|
||||||
|
|
||||||
|
JX.behavior('reorder-applications', function(config) {
|
||||||
|
|
||||||
|
var root = JX.$(config.listID);
|
||||||
|
|
||||||
|
var list = new JX.DraggableList('pinned-application', root)
|
||||||
|
.setFindItemsHandler(function() {
|
||||||
|
return JX.DOM.scry(root, 'li', 'pinned-application');
|
||||||
|
});
|
||||||
|
|
||||||
|
list.listen('didDrop', function(node, after) {
|
||||||
|
var nodes = list.findItems();
|
||||||
|
var order = [];
|
||||||
|
var key;
|
||||||
|
for (var ii = 0; ii < nodes.length; ii++) {
|
||||||
|
key = JX.Stratcom.getData(nodes[ii]).applicationClass;
|
||||||
|
if (key) {
|
||||||
|
order.push(key);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
list.lock();
|
||||||
|
JX.DOM.alterClass(node, 'drag-sending', true);
|
||||||
|
|
||||||
|
new JX.Workflow(config.panelURI, {order: order.join()})
|
||||||
|
.start();
|
||||||
|
});
|
||||||
|
|
||||||
|
});
|
Loading…
Reference in a new issue