Page Menu
Home
Phabricator
Search
Configure Global Search
Log In
Files
F15376478
D9332.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Award Token
Flag For Later
Size
23 KB
Referenced Files
None
Subscribers
None
D9332.diff
View Options
diff --git a/resources/celerity/map.php b/resources/celerity/map.php
--- a/resources/celerity/map.php
+++ b/resources/celerity/map.php
@@ -100,7 +100,6 @@
'rsrc/css/application/releeph/releeph-request-differential-create-dialog.css' => '8d8b92cd',
'rsrc/css/application/releeph/releeph-request-typeahead.css' => '667a48ae',
'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/subscriptions/subscribers-list.css' => '5bb30c78',
'rsrc/css/application/tokens/tokens.css' => '3d0f239e',
@@ -468,6 +467,7 @@
'rsrc/js/core/behavior-phabricator-remarkup-assist.js' => 'c021950a',
'rsrc/js/core/behavior-refresh-csrf.js' => '7814b593',
'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-search-typeahead.js' => '86549ee3',
'rsrc/js/core/behavior-select-on-click.js' => '0e34ca02',
@@ -629,6 +629,7 @@
'javelin-behavior-releeph-request-state-change' => 'd259e7c9',
'javelin-behavior-releeph-request-typeahead' => 'cd9e7094',
'javelin-behavior-remarkup-preview' => 'f7379f45',
+ 'javelin-behavior-reorder-applications' => 'a8e3795d',
'javelin-behavior-repository-crossreference' => '8ab282be',
'javelin-behavior-search-reorder-queries' => '37871df4',
'javelin-behavior-select-on-click' => '0e34ca02',
@@ -720,7 +721,6 @@
'phabricator-project-tag-css' => '095c9404',
'phabricator-remarkup-css' => '80c3a48c',
'phabricator-search-results-css' => 'f240504c',
- 'phabricator-settings-css' => 'ea8f5915',
'phabricator-shaped-request' => '7cbe244b',
'phabricator-side-menu-view-css' => 'c1986b85',
'phabricator-slowvote-css' => '266df6a1',
@@ -1612,6 +1612,14 @@
1 => 'javelin-dom',
2 => 'javelin-stratcom',
),
+ 'a8e3795d' =>
+ array(
+ 0 => 'javelin-behavior',
+ 1 => 'javelin-stratcom',
+ 2 => 'javelin-workflow',
+ 3 => 'javelin-dom',
+ 4 => 'phabricator-draggable-list',
+ ),
'a9aaba0c' =>
array(
0 => 'javelin-behavior',
diff --git a/src/applications/home/controller/PhabricatorHomeController.php b/src/applications/home/controller/PhabricatorHomeController.php
--- a/src/applications/home/controller/PhabricatorHomeController.php
+++ b/src/applications/home/controller/PhabricatorHomeController.php
@@ -25,13 +25,10 @@
->setViewer($user)
->withInstalled(true)
->withUnlisted(false)
+ ->withLaunchable(true)
->execute();
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).
@@ -39,115 +36,45 @@
}
}
- $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;
- }
+ $pinned = $user->loadPreferences()->getPinnedApplications(
+ $applications,
+ $user);
- $tile_groups = array_select_keys(
- $tile_groups,
- array(
- PhabricatorApplication::TILE_FULL,
- PhabricatorApplication::TILE_SHOW,
- PhabricatorApplication::TILE_HIDE,
- ));
+ // Put "Applications" at the bottom.
+ $meta_app = 'PhabricatorApplicationApplications';
+ $pinned = array_fuse($pinned);
+ unset($pinned[$meta_app]);
+ $pinned[$meta_app] = $meta_app;
- foreach ($tile_groups as $tile_display => $tile_group) {
- if (!$tile_group) {
+ $tiles = array();
+ foreach ($pinned as $pinned_application) {
+ if (empty($applications[$pinned_application])) {
continue;
}
- $is_small_tiles = ($tile_display == PhabricatorApplication::TILE_SHOW) ||
- ($tile_display == PhabricatorApplication::TILE_HIDE);
+ $application = $applications[$pinned_application];
- 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);
- }
+ $tile = id(new PhabricatorApplicationLaunchView())
+ ->setApplication($application)
+ ->setApplicationStatus($application->loadStatus($user))
+ ->setUser($user);
- $is_hide = ($tile_display == PhabricatorApplication::TILE_HIDE);
- 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);
- }
+ $tiles[] = $tile;
}
+ $nav->addCustomBlock(
+ phutil_tag(
+ 'div',
+ array(
+ 'class' => 'application-tile-group',
+ ),
+ $tiles));
+
$nav->addFilter(
'',
pht('Customize Applications...'),
'/settings/panel/home/');
+
$nav->addClass('phabricator-side-menu-home');
$nav->selectFilter(null);
diff --git a/src/applications/settings/panel/PhabricatorSettingsPanelHomePreferences.php b/src/applications/settings/panel/PhabricatorSettingsPanelHomePreferences.php
--- a/src/applications/settings/panel/PhabricatorSettingsPanelHomePreferences.php
+++ b/src/applications/settings/panel/PhabricatorSettingsPanelHomePreferences.php
@@ -19,194 +19,179 @@
$user = $request->getUser();
$preferences = $user->loadPreferences();
- require_celerity_resource('phabricator-settings-css');
-
$apps = id(new PhabricatorApplicationQuery())
->setViewer($user)
->withInstalled(true)
->withUnlisted(false)
+ ->withLaunchable(true)
->execute();
- $pref_tiles = PhabricatorUserPreferences::PREFERENCE_APP_TILES;
- $tiles = $preferences->getPreference($pref_tiles, array());
+ $pinned = $preferences->getPinnedApplications($apps, $user);
- 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;
- }
+ $app_list = array();
+ foreach ($pinned as $app) {
+ if (isset($apps[$app])) {
+ $app_list[$app] = $apps[$app];
}
- $preferences->setPreference($pref_tiles, $tiles);
- $preferences->save();
-
- return id(new AphrontRedirectResponse())
- ->setURI($this->getPanelURI('?saved=true'));
}
- $form = id(new AphrontFormView())
- ->setUser($user);
-
- $group_map = PhabricatorApplication::getApplicationGroups();
-
- $output = array();
+ if ($request->getBool('add')) {
+ $options = array();
+ foreach ($apps as $app) {
+ $options[get_class($app)] = $app->getName();
+ }
+ asort($options);
- $app_groups = mgroup($apps, 'getApplicationGroup');
- $app_groups = array_select_keys($app_groups, array_keys($group_map));
+ unset($options['PhabricatorApplicationApplications']);
- foreach ($app_groups as $group => $apps) {
- $group_name = $group_map[$group];
- $rows = array();
+ if ($request->isFormPost()) {
+ $pin = $request->getStr('pin');
+ if (isset($options[$pin]) && !in_array($pin, $pinned)) {
+ $pinned[] = $pin;
+ $preferences->setPreference(
+ PhabricatorUserPreferences::PREFERENCE_APP_PINNED,
+ $pinned);
+ $preferences->save();
- foreach ($apps as $app) {
- if (!$app->shouldAppearInLaunchView()) {
- continue;
+ return id(new AphrontRedirectResponse())
+ ->setURI($this->getPanelURI());
}
+ }
+
+ $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);
+ }
- $default = $app->getDefaultTileDisplay($user);
- if ($default == PhabricatorApplication::TILE_INVISIBLE) {
- continue;
+ $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());
}
- $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,
- );
+ $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);
}
+ }
- if (empty($rows)) {
- continue;
- }
+ $order = $request->getStrList('order');
+ if ($order && $request->validateCSRF()) {
+ $preferences->setPreference(
+ PhabricatorUserPreferences::PREFERENCE_APP_PINNED,
+ $order);
+ $preferences->save();
- $table = new AphrontTableView($rows);
-
- $table
- ->setClassName('phabricator-settings-homepagetable')
- ->setHeaders(
- array(
- pht('Applications'),
- pht('Default'),
- pht('Hidden'),
- pht('Small'),
- pht('Large'),
- ))
- ->setColumnClasses(
- array(
- '',
- 'fixed',
- 'fixed',
- 'fixed',
- 'fixed',
- ));
-
-
- $panel = id(new PHUIObjectBoxView())
- ->setHeaderText($group_name)
- ->appendChild($table);
-
- $output[] = $panel;
+ return id(new AphrontRedirectResponse())
+ ->setURI($this->getPanelURI());
}
- $save_button =
- id(new AphrontFormSubmitControl())
- ->setValue(pht('Save Preferences'));
+ $list_id = celerity_generate_unique_node_id();
- $output[] = id(new PHUIBoxView())
- ->addPadding(PHUI::PADDING_LARGE)
- ->addClass('phabricator-settings-homepagetable-button')
- ->appendChild($save_button);
+ $list = id(new PHUIObjectItemListView())
+ ->setUser($user)
+ ->setID($list_id)
+ ->setFlush(true);
- $form->appendChild($output);
+ Javelin::initBehavior(
+ 'reorder-applications',
+ array(
+ 'listID' => $list_id,
+ 'panelURI' => $this->getPanelURI(),
+ ));
- $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.')));
- }
+ foreach ($app_list as $key => $application) {
+ if ($key == 'PhabricatorApplicationApplications') {
+ continue;
+ }
- $header = id(new PHUIHeaderView())
- ->setHeader(pht('Home Page Preferences'));
+ $icon = $application->getIconName();
+ if (!$icon) {
+ $icon = 'application';
+ }
- $form = id(new PHUIBoxView())
- ->addClass('phabricator-settings-homepagetable-wrap')
- ->appendChild($form);
+ $icon_view = javelin_tag(
+ 'span',
+ array(
+ 'class' => 'phui-icon-view '.
+ 'sprite-apps-large apps-'.$icon.'-dark-large',
+ 'aural' => false,
+ ),
+ '');
+
+ $item = id(new PHUIObjectItemView())
+ ->setHeader($application->getName())
+ ->setImageIcon($icon_view)
+ ->addAttribute($application->getShortDescription())
+ ->setGrippable(true);
+
+ $item->addAction(
+ id(new PHUIListItemView())
+ ->setIcon('fa-times')
+ ->setHref($this->getPanelURI().'?unpin='.$key)
+ ->setWorkflow(true));
+
+ $item->addSigil('pinned-application');
+ $item->setMetadata(
+ array(
+ 'applicationClass' => $key,
+ ));
+
+ $list->addItem($item);
+ }
- return array($header, $error_view, $form);
+ $header = id(new PHUIHeaderView())
+ ->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')));
+
+ $box = id(new PHUIObjectBoxView())
+ ->setHeader($header)
+ ->appendChild($list);
+
+ return $box;
}
}
diff --git a/src/applications/settings/storage/PhabricatorUserPreferences.php b/src/applications/settings/storage/PhabricatorUserPreferences.php
--- a/src/applications/settings/storage/PhabricatorUserPreferences.php
+++ b/src/applications/settings/storage/PhabricatorUserPreferences.php
@@ -24,6 +24,7 @@
const PREFERENCE_NAV_COLLAPSED = 'nav-collapsed';
const PREFERENCE_NAV_WIDTH = 'nav-width';
const PREFERENCE_APP_TILES = 'app-tiles';
+ const PREFERENCE_APP_PINNED = 'app-pinned';
const PREFERENCE_DIFF_FILETREE = 'diff-filetree';
@@ -55,4 +56,31 @@
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;
+ }
+
}
diff --git a/src/view/form/control/AphrontFormSelectControl.php b/src/view/form/control/AphrontFormSelectControl.php
--- a/src/view/form/control/AphrontFormSelectControl.php
+++ b/src/view/form/control/AphrontFormSelectControl.php
@@ -7,6 +7,7 @@
}
private $options;
+ private $disabledOptions = array();
public function setOptions(array $options) {
$this->options = $options;
@@ -17,6 +18,11 @@
return $this->options;
}
+ public function setDisabledOptions(array $disabled) {
+ $this->disabledOptions = $disabled;
+ return $this;
+ }
+
protected function renderInput() {
return self::renderSelectTag(
$this->getValue(),
@@ -25,15 +31,17 @@
'name' => $this->getName(),
'disabled' => $this->getDisabled() ? 'disabled' : null,
'id' => $this->getID(),
- ));
+ ),
+ $this->disabledOptions);
}
public static function renderSelectTag(
$selected,
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(
'select',
@@ -41,7 +49,12 @@
$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();
foreach ($options as $value => $thing) {
if (is_array($thing)) {
@@ -57,6 +70,7 @@
array(
'selected' => ($value == $selected) ? 'selected' : null,
'value' => $value,
+ 'disabled' => isset($disabled[$value]) ? 'disabled' : null,
),
$thing);
}
diff --git a/webroot/rsrc/css/application/settings/settings.css b/webroot/rsrc/css/application/settings/settings.css
deleted file mode 100644
--- a/webroot/rsrc/css/application/settings/settings.css
+++ /dev/null
@@ -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;
-}
diff --git a/webroot/rsrc/js/core/behavior-reorder-applications.js b/webroot/rsrc/js/core/behavior-reorder-applications.js
new file mode 100644
--- /dev/null
+++ b/webroot/rsrc/js/core/behavior-reorder-applications.js
@@ -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();
+ });
+
+});
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Fri, Mar 14, 3:56 AM (1 w, 2 d ago)
Storage Engine
blob
Storage Format
Encrypted (AES-256-CBC)
Storage Handle
7644496
Default Alt Text
D9332.diff (23 KB)
Attached To
Mode
D9332: Remove application small/hidden tiles
Attached
Detach File
Event Timeline
Log In to Comment