@recaptime-dev's working patches + fork for Phorge, a community fork of Phabricator. (Upstream dev and stable branches are at upstream/main and upstream/stable respectively.) hq.recaptime.dev/wiki/Phorge
phorge phabricator
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

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

+253 -279
+10 -2
resources/celerity/map.php
··· 100 100 'rsrc/css/application/releeph/releeph-request-differential-create-dialog.css' => '8d8b92cd', 101 101 'rsrc/css/application/releeph/releeph-request-typeahead.css' => '667a48ae', 102 102 'rsrc/css/application/search/search-results.css' => 'f240504c', 103 - 'rsrc/css/application/settings/settings.css' => 'ea8f5915', 104 103 'rsrc/css/application/slowvote/slowvote.css' => '266df6a1', 105 104 'rsrc/css/application/subscriptions/subscribers-list.css' => '5bb30c78', 106 105 'rsrc/css/application/tokens/tokens.css' => '3d0f239e', ··· 468 467 'rsrc/js/core/behavior-phabricator-remarkup-assist.js' => 'c021950a', 469 468 'rsrc/js/core/behavior-refresh-csrf.js' => '7814b593', 470 469 'rsrc/js/core/behavior-remarkup-preview.js' => 'f7379f45', 470 + 'rsrc/js/core/behavior-reorder-applications.js' => 'a8e3795d', 471 471 'rsrc/js/core/behavior-reveal-content.js' => '8f24abfc', 472 472 'rsrc/js/core/behavior-search-typeahead.js' => '86549ee3', 473 473 'rsrc/js/core/behavior-select-on-click.js' => '0e34ca02', ··· 629 629 'javelin-behavior-releeph-request-state-change' => 'd259e7c9', 630 630 'javelin-behavior-releeph-request-typeahead' => 'cd9e7094', 631 631 'javelin-behavior-remarkup-preview' => 'f7379f45', 632 + 'javelin-behavior-reorder-applications' => 'a8e3795d', 632 633 'javelin-behavior-repository-crossreference' => '8ab282be', 633 634 'javelin-behavior-search-reorder-queries' => '37871df4', 634 635 'javelin-behavior-select-on-click' => '0e34ca02', ··· 720 721 'phabricator-project-tag-css' => '095c9404', 721 722 'phabricator-remarkup-css' => '80c3a48c', 722 723 'phabricator-search-results-css' => 'f240504c', 723 - 'phabricator-settings-css' => 'ea8f5915', 724 724 'phabricator-shaped-request' => '7cbe244b', 725 725 'phabricator-side-menu-view-css' => 'c1986b85', 726 726 'phabricator-slowvote-css' => '266df6a1', ··· 1611 1611 0 => 'javelin-behavior', 1612 1612 1 => 'javelin-dom', 1613 1613 2 => 'javelin-stratcom', 1614 + ), 1615 + 'a8e3795d' => 1616 + array( 1617 + 0 => 'javelin-behavior', 1618 + 1 => 'javelin-stratcom', 1619 + 2 => 'javelin-workflow', 1620 + 3 => 'javelin-dom', 1621 + 4 => 'phabricator-draggable-list', 1614 1622 ), 1615 1623 'a9aaba0c' => 1616 1624 array(
+27 -100
src/applications/home/controller/PhabricatorHomeController.php
··· 25 25 ->setViewer($user) 26 26 ->withInstalled(true) 27 27 ->withUnlisted(false) 28 + ->withLaunchable(true) 28 29 ->execute(); 29 30 30 31 foreach ($applications as $key => $application) { 31 - if (!$application->shouldAppearInLaunchView()) { 32 - // Remove hidden applications (usually internal stuff). 33 - unset($applications[$key]); 34 - } 35 32 $invisible = PhabricatorApplication::TILE_INVISIBLE; 36 33 if ($application->getDefaultTileDisplay($user) == $invisible) { 37 34 // Remove invisible applications (e.g., admin apps for non-admins). ··· 39 36 } 40 37 } 41 38 42 - $status = array(); 43 - foreach ($applications as $key => $application) { 44 - $status[get_class($application)] = $application->loadStatus($user); 45 - } 46 - 47 - $tile_groups = array(); 48 - $prefs = $user->loadPreferences()->getPreference( 49 - PhabricatorUserPreferences::PREFERENCE_APP_TILES, 50 - array()); 51 - foreach ($applications as $key => $application) { 52 - $display = idx( 53 - $prefs, 54 - get_class($application), 55 - $application->getDefaultTileDisplay($user)); 56 - $tile_groups[$display][] = $application; 57 - } 39 + $pinned = $user->loadPreferences()->getPinnedApplications( 40 + $applications, 41 + $user); 58 42 59 - $tile_groups = array_select_keys( 60 - $tile_groups, 61 - array( 62 - PhabricatorApplication::TILE_FULL, 63 - PhabricatorApplication::TILE_SHOW, 64 - PhabricatorApplication::TILE_HIDE, 65 - )); 43 + // Put "Applications" at the bottom. 44 + $meta_app = 'PhabricatorApplicationApplications'; 45 + $pinned = array_fuse($pinned); 46 + unset($pinned[$meta_app]); 47 + $pinned[$meta_app] = $meta_app; 66 48 67 - foreach ($tile_groups as $tile_display => $tile_group) { 68 - if (!$tile_group) { 49 + $tiles = array(); 50 + foreach ($pinned as $pinned_application) { 51 + if (empty($applications[$pinned_application])) { 69 52 continue; 70 53 } 71 54 72 - $is_small_tiles = ($tile_display == PhabricatorApplication::TILE_SHOW) || 73 - ($tile_display == PhabricatorApplication::TILE_HIDE); 55 + $application = $applications[$pinned_application]; 74 56 75 - if ($is_small_tiles) { 76 - $groups = PhabricatorApplication::getApplicationGroups(); 77 - $tile_group = mgroup($tile_group, 'getApplicationGroup'); 78 - $tile_group = array_select_keys($tile_group, array_keys($groups)); 79 - } else { 80 - $tile_group = array($tile_group); 81 - } 57 + $tile = id(new PhabricatorApplicationLaunchView()) 58 + ->setApplication($application) 59 + ->setApplicationStatus($application->loadStatus($user)) 60 + ->setUser($user); 82 61 83 - $is_hide = ($tile_display == PhabricatorApplication::TILE_HIDE); 84 - if ($is_hide) { 85 - $show_item_id = celerity_generate_unique_node_id(); 86 - $hide_item_id = celerity_generate_unique_node_id(); 62 + $tiles[] = $tile; 63 + } 87 64 88 - $show_item = id(new PHUIListItemView()) 89 - ->setName(pht('Show More Applications')) 90 - ->setHref('#') 91 - ->addSigil('reveal-content') 92 - ->setID($show_item_id); 93 - 94 - $hide_item = id(new PHUIListItemView()) 95 - ->setName(pht('Show Fewer Applications')) 96 - ->setHref('#') 97 - ->setStyle('display: none') 98 - ->setID($hide_item_id) 99 - ->addSigil('reveal-content'); 100 - 101 - $nav->addMenuItem($show_item); 102 - $tile_ids = array($hide_item_id); 103 - } 104 - 105 - foreach ($tile_group as $group => $application_list) { 106 - $tiles = array(); 107 - foreach ($application_list as $key => $application) { 108 - $tile = id(new PhabricatorApplicationLaunchView()) 109 - ->setApplication($application) 110 - ->setApplicationStatus( 111 - idx($status, get_class($application), array())) 112 - ->setUser($user); 113 - 114 - $tiles[] = $tile; 115 - } 116 - 117 - $group_id = celerity_generate_unique_node_id(); 118 - $tile_ids[] = $group_id; 119 - $nav->addCustomBlock( 120 - phutil_tag( 121 - 'div', 122 - array( 123 - 'class' => 'application-tile-group', 124 - 'id' => $group_id, 125 - 'style' => ($is_hide ? 'display: none' : null), 126 - ), 127 - mpull($tiles, 'render'))); 128 - } 129 - 130 - if ($is_hide) { 131 - Javelin::initBehavior('phabricator-reveal-content'); 132 - 133 - $show_item->setMetadata( 134 - array( 135 - 'showIDs' => $tile_ids, 136 - 'hideIDs' => array($show_item_id), 137 - )); 138 - $hide_item->setMetadata( 139 - array( 140 - 'showIDs' => array($show_item_id), 141 - 'hideIDs' => $tile_ids, 142 - )); 143 - $nav->addMenuItem($hide_item); 144 - } 145 - } 65 + $nav->addCustomBlock( 66 + phutil_tag( 67 + 'div', 68 + array( 69 + 'class' => 'application-tile-group', 70 + ), 71 + $tiles)); 146 72 147 73 $nav->addFilter( 148 74 '', 149 75 pht('Customize Applications...'), 150 76 '/settings/panel/home/'); 77 + 151 78 $nav->addClass('phabricator-side-menu-home'); 152 79 $nav->selectFilter(null); 153 80
+133 -148
src/applications/settings/panel/PhabricatorSettingsPanelHomePreferences.php
··· 19 19 $user = $request->getUser(); 20 20 $preferences = $user->loadPreferences(); 21 21 22 - require_celerity_resource('phabricator-settings-css'); 23 - 24 22 $apps = id(new PhabricatorApplicationQuery()) 25 23 ->setViewer($user) 26 24 ->withInstalled(true) 27 25 ->withUnlisted(false) 26 + ->withLaunchable(true) 28 27 ->execute(); 29 28 30 - $pref_tiles = PhabricatorUserPreferences::PREFERENCE_APP_TILES; 31 - $tiles = $preferences->getPreference($pref_tiles, array()); 29 + $pinned = $preferences->getPinnedApplications($apps, $user); 32 30 33 - if ($request->isFormPost()) { 34 - $values = $request->getArr('tile'); 35 - foreach ($apps as $app) { 36 - $key = get_class($app); 37 - $value = idx($values, $key); 38 - switch ($value) { 39 - case PhabricatorApplication::TILE_FULL: 40 - case PhabricatorApplication::TILE_SHOW: 41 - case PhabricatorApplication::TILE_HIDE: 42 - $tiles[$key] = $value; 43 - break; 44 - default: 45 - unset($tiles[$key]); 46 - break; 47 - } 31 + $app_list = array(); 32 + foreach ($pinned as $app) { 33 + if (isset($apps[$app])) { 34 + $app_list[$app] = $apps[$app]; 48 35 } 49 - $preferences->setPreference($pref_tiles, $tiles); 50 - $preferences->save(); 51 - 52 - return id(new AphrontRedirectResponse()) 53 - ->setURI($this->getPanelURI('?saved=true')); 54 36 } 55 37 56 - $form = id(new AphrontFormView()) 57 - ->setUser($user); 38 + if ($request->getBool('add')) { 39 + $options = array(); 40 + foreach ($apps as $app) { 41 + $options[get_class($app)] = $app->getName(); 42 + } 43 + asort($options); 58 44 59 - $group_map = PhabricatorApplication::getApplicationGroups(); 45 + unset($options['PhabricatorApplicationApplications']); 60 46 61 - $output = array(); 62 - 63 - $app_groups = mgroup($apps, 'getApplicationGroup'); 64 - $app_groups = array_select_keys($app_groups, array_keys($group_map)); 47 + if ($request->isFormPost()) { 48 + $pin = $request->getStr('pin'); 49 + if (isset($options[$pin]) && !in_array($pin, $pinned)) { 50 + $pinned[] = $pin; 51 + $preferences->setPreference( 52 + PhabricatorUserPreferences::PREFERENCE_APP_PINNED, 53 + $pinned); 54 + $preferences->save(); 65 55 66 - foreach ($app_groups as $group => $apps) { 67 - $group_name = $group_map[$group]; 68 - $rows = array(); 69 - 70 - foreach ($apps as $app) { 71 - if (!$app->shouldAppearInLaunchView()) { 72 - continue; 56 + return id(new AphrontRedirectResponse()) 57 + ->setURI($this->getPanelURI()); 73 58 } 59 + } 74 60 75 - $default = $app->getDefaultTileDisplay($user); 76 - if ($default == PhabricatorApplication::TILE_INVISIBLE) { 77 - continue; 78 - } 61 + $options_control = id(new AphrontFormSelectControl()) 62 + ->setName('pin') 63 + ->setLabel(pht('Application')) 64 + ->setOptions($options) 65 + ->setDisabledOptions(array_keys($app_list)); 79 66 80 - $default_name = PhabricatorApplication::getTileDisplayName($default); 67 + $form = id(new AphrontFormView()) 68 + ->setUser($user) 69 + ->addHiddenInput('add', 'true') 70 + ->appendRemarkupInstructions( 71 + pht('Choose an application to pin to your home page.')) 72 + ->appendChild($options_control); 81 73 82 - $hide = PhabricatorApplication::TILE_HIDE; 83 - $show = PhabricatorApplication::TILE_SHOW; 84 - $full = PhabricatorApplication::TILE_FULL; 74 + $dialog = id(new AphrontDialogView()) 75 + ->setUser($user) 76 + ->setWidth(AphrontDialogView::WIDTH_FORM) 77 + ->setTitle(pht('Pin Application')) 78 + ->appendChild($form->buildLayoutView()) 79 + ->addSubmitButton(pht('Pin Application')) 80 + ->addCancelButton($this->getPanelURI()); 85 81 86 - $key = get_class($app); 82 + return id(new AphrontDialogResponse())->setDialog($dialog); 83 + } 87 84 88 - $default_radio_button_status = 89 - (idx($tiles, $key, 'default') == 'default') ? 'checked' : null; 85 + $unpin = $request->getStr('unpin'); 86 + if ($unpin) { 87 + $app = idx($apps, $unpin); 88 + if ($app) { 89 + if ($request->isFormPost()) { 90 + $pinned = array_diff($pinned, array($unpin)); 91 + $preferences->setPreference( 92 + PhabricatorUserPreferences::PREFERENCE_APP_PINNED, 93 + $pinned); 94 + $preferences->save(); 90 95 91 - $hide_radio_button_status = 92 - (idx($tiles, $key, 'default') == $hide) ? 'checked' : null; 96 + return id(new AphrontRedirectResponse()) 97 + ->setURI($this->getPanelURI()); 98 + } 93 99 94 - $show_radio_button_status = 95 - (idx($tiles, $key, 'default') == $show) ? 'checked' : null; 100 + $dialog = id(new AphrontDialogView()) 101 + ->setUser($user) 102 + ->setTitle(pht('Unpin Application')) 103 + ->appendParagraph( 104 + pht( 105 + 'Unpin the %s application from your home page?', 106 + phutil_tag('strong', array(), $app->getName()))) 107 + ->addSubmitButton(pht('Unpin Application')) 108 + ->addCanceLButton($this->getPanelURI()); 96 109 97 - $full_radio_button_status = 98 - (idx($tiles, $key, 'default') == $full) ? 'checked' : null; 110 + return id(new AphrontDialogResponse())->setDialog($dialog); 111 + } 112 + } 99 113 114 + $order = $request->getStrList('order'); 115 + if ($order && $request->validateCSRF()) { 116 + $preferences->setPreference( 117 + PhabricatorUserPreferences::PREFERENCE_APP_PINNED, 118 + $order); 119 + $preferences->save(); 100 120 101 - $default_radio_button = phutil_tag( 102 - 'input', 103 - array( 104 - 'type' => 'radio', 105 - 'name' => 'tile['.$key.']', 106 - 'value' => 'default', 107 - 'checked' => $default_radio_button_status, 108 - )); 121 + return id(new AphrontRedirectResponse()) 122 + ->setURI($this->getPanelURI()); 123 + } 109 124 110 - $hide_radio_button = phutil_tag( 111 - 'input', 112 - array( 113 - 'type' => 'radio', 114 - 'name' => 'tile['.$key.']', 115 - 'value' => $hide, 116 - 'checked' => $hide_radio_button_status, 117 - )); 125 + $list_id = celerity_generate_unique_node_id(); 118 126 119 - $show_radio_button = phutil_tag( 120 - 'input', 121 - array( 122 - 'type' => 'radio', 123 - 'name' => 'tile['.$key.']', 124 - 'value' => $show, 125 - 'checked' => $show_radio_button_status, 126 - )); 127 - 128 - $full_radio_button = phutil_tag( 129 - 'input', 130 - array( 131 - 'type' => 'radio', 132 - 'name' => 'tile['.$key.']', 133 - 'value' => $full, 134 - 'checked' => $full_radio_button_status, 135 - )); 136 - 137 - $desc = $app->getShortDescription(); 138 - $app_column = hsprintf( 139 - "<strong>%s</strong><br/ >%s, <em>Default: %s</em>", 140 - $app->getName(), $desc, $default_name); 127 + $list = id(new PHUIObjectItemListView()) 128 + ->setUser($user) 129 + ->setID($list_id) 130 + ->setFlush(true); 141 131 142 - $rows[] = array( 143 - $app_column, 144 - $default_radio_button, 145 - $hide_radio_button, 146 - $show_radio_button, 147 - $full_radio_button, 148 - ); 149 - } 132 + Javelin::initBehavior( 133 + 'reorder-applications', 134 + array( 135 + 'listID' => $list_id, 136 + 'panelURI' => $this->getPanelURI(), 137 + )); 150 138 151 - if (empty($rows)) { 139 + foreach ($app_list as $key => $application) { 140 + if ($key == 'PhabricatorApplicationApplications') { 152 141 continue; 153 142 } 154 143 155 - $table = new AphrontTableView($rows); 156 - 157 - $table 158 - ->setClassName('phabricator-settings-homepagetable') 159 - ->setHeaders( 160 - array( 161 - pht('Applications'), 162 - pht('Default'), 163 - pht('Hidden'), 164 - pht('Small'), 165 - pht('Large'), 166 - )) 167 - ->setColumnClasses( 168 - array( 169 - '', 170 - 'fixed', 171 - 'fixed', 172 - 'fixed', 173 - 'fixed', 174 - )); 144 + $icon = $application->getIconName(); 145 + if (!$icon) { 146 + $icon = 'application'; 147 + } 175 148 149 + $icon_view = javelin_tag( 150 + 'span', 151 + array( 152 + 'class' => 'phui-icon-view '. 153 + 'sprite-apps-large apps-'.$icon.'-dark-large', 154 + 'aural' => false, 155 + ), 156 + ''); 176 157 177 - $panel = id(new PHUIObjectBoxView()) 178 - ->setHeaderText($group_name) 179 - ->appendChild($table); 158 + $item = id(new PHUIObjectItemView()) 159 + ->setHeader($application->getName()) 160 + ->setImageIcon($icon_view) 161 + ->addAttribute($application->getShortDescription()) 162 + ->setGrippable(true); 180 163 181 - $output[] = $panel; 182 - } 183 - 184 - $save_button = 185 - id(new AphrontFormSubmitControl()) 186 - ->setValue(pht('Save Preferences')); 187 - 188 - $output[] = id(new PHUIBoxView()) 189 - ->addPadding(PHUI::PADDING_LARGE) 190 - ->addClass('phabricator-settings-homepagetable-button') 191 - ->appendChild($save_button); 164 + $item->addAction( 165 + id(new PHUIListItemView()) 166 + ->setIcon('fa-times') 167 + ->setHref($this->getPanelURI().'?unpin='.$key) 168 + ->setWorkflow(true)); 192 169 193 - $form->appendChild($output); 170 + $item->addSigil('pinned-application'); 171 + $item->setMetadata( 172 + array( 173 + 'applicationClass' => $key, 174 + )); 194 175 195 - $error_view = null; 196 - if ($request->getStr('saved') === 'true') { 197 - $error_view = id(new AphrontErrorView()) 198 - ->setTitle(pht('Preferences Saved')) 199 - ->setSeverity(AphrontErrorView::SEVERITY_NOTICE) 200 - ->setErrors(array(pht('Your preferences have been saved.'))); 176 + $list->addItem($item); 201 177 } 202 178 203 179 $header = id(new PHUIHeaderView()) 204 - ->setHeader(pht('Home Page Preferences')); 180 + ->setHeader(pht('Pinned Applications')) 181 + ->addActionLink( 182 + id(new PHUIButtonView()) 183 + ->setTag('a') 184 + ->setText(pht('Pin Application')) 185 + ->setHref($this->getPanelURI().'?add=true') 186 + ->setWorkflow(true) 187 + ->setIcon( 188 + id(new PHUIIconView()) 189 + ->setIconFont('fa-thumb-tack'))); 205 190 206 - $form = id(new PHUIBoxView()) 207 - ->addClass('phabricator-settings-homepagetable-wrap') 208 - ->appendChild($form); 191 + $box = id(new PHUIObjectBoxView()) 192 + ->setHeader($header) 193 + ->appendChild($list); 209 194 210 - return array($header, $error_view, $form); 195 + return $box; 211 196 } 212 197 }
+28
src/applications/settings/storage/PhabricatorUserPreferences.php
··· 24 24 const PREFERENCE_NAV_COLLAPSED = 'nav-collapsed'; 25 25 const PREFERENCE_NAV_WIDTH = 'nav-width'; 26 26 const PREFERENCE_APP_TILES = 'app-tiles'; 27 + const PREFERENCE_APP_PINNED = 'app-pinned'; 27 28 28 29 const PREFERENCE_DIFF_FILETREE = 'diff-filetree'; 29 30 ··· 53 54 public function unsetPreference($key) { 54 55 unset($this->preferences[$key]); 55 56 return $this; 57 + } 58 + 59 + public function getPinnedApplications(array $apps, PhabricatorUser $viewer) { 60 + $pref_pinned = PhabricatorUserPreferences::PREFERENCE_APP_PINNED; 61 + $pinned = $this->getPreference($pref_pinned); 62 + 63 + if ($pinned) { 64 + return $pinned; 65 + } 66 + 67 + $pref_tiles = PhabricatorUserPreferences::PREFERENCE_APP_TILES; 68 + $tiles = $this->getPreference($pref_tiles, array()); 69 + 70 + $large = array(); 71 + foreach ($apps as $app) { 72 + $tile = $app->getDefaultTileDisplay($viewer); 73 + 74 + if (isset($tiles[get_class($app)])) { 75 + $tile = $tiles[get_class($app)]; 76 + } 77 + 78 + if ($tile == PhabricatorApplication::TILE_FULL) { 79 + $large[] = get_class($app); 80 + } 81 + } 82 + 83 + return $large; 56 84 } 57 85 58 86 }
+18 -4
src/view/form/control/AphrontFormSelectControl.php
··· 7 7 } 8 8 9 9 private $options; 10 + private $disabledOptions = array(); 10 11 11 12 public function setOptions(array $options) { 12 13 $this->options = $options; ··· 15 16 16 17 public function getOptions() { 17 18 return $this->options; 19 + } 20 + 21 + public function setDisabledOptions(array $disabled) { 22 + $this->disabledOptions = $disabled; 23 + return $this; 18 24 } 19 25 20 26 protected function renderInput() { ··· 25 31 'name' => $this->getName(), 26 32 'disabled' => $this->getDisabled() ? 'disabled' : null, 27 33 'id' => $this->getID(), 28 - )); 34 + ), 35 + $this->disabledOptions); 29 36 } 30 37 31 38 public static function renderSelectTag( 32 39 $selected, 33 40 array $options, 34 - array $attrs = array()) { 41 + array $attrs = array(), 42 + array $disabled = array()) { 35 43 36 - $option_tags = self::renderOptions($selected, $options); 44 + $option_tags = self::renderOptions($selected, $options, $disabled); 37 45 38 46 return javelin_tag( 39 47 'select', ··· 41 49 $option_tags); 42 50 } 43 51 44 - private static function renderOptions($selected, array $options) { 52 + private static function renderOptions( 53 + $selected, 54 + array $options, 55 + array $disabled = array()) { 56 + $disabled = array_fuse($disabled); 57 + 45 58 $tags = array(); 46 59 foreach ($options as $value => $thing) { 47 60 if (is_array($thing)) { ··· 57 70 array( 58 71 'selected' => ($value == $selected) ? 'selected' : null, 59 72 'value' => $value, 73 + 'disabled' => isset($disabled[$value]) ? 'disabled' : null, 60 74 ), 61 75 $thing); 62 76 }
-25
webroot/rsrc/css/application/settings/settings.css
··· 1 - /** 2 - * @provides phabricator-settings-css 3 - */ 4 - 5 - .phabricator-settings-homepagetable .fixed { 6 - width: 48px; 7 - text-align: center; 8 - } 9 - 10 - .phabricator-settings-homepagetable td em { 11 - color: {$lightgreytext}; 12 - } 13 - 14 - .phabricator-settings-homepagetable-button .aphront-form-input { 15 - margin: 0; 16 - width: auto; 17 - } 18 - 19 - .phabricator-settings-homepagetable-button .aphront-form-control { 20 - padding: 0; 21 - } 22 - 23 - .phabricator-settings-homepagetable-wrap .phui-form-view { 24 - padding: 0; 25 - }
+37
webroot/rsrc/js/core/behavior-reorder-applications.js
··· 1 + /** 2 + * @provides javelin-behavior-reorder-applications 3 + * @requires javelin-behavior 4 + * javelin-stratcom 5 + * javelin-workflow 6 + * javelin-dom 7 + * phabricator-draggable-list 8 + */ 9 + 10 + JX.behavior('reorder-applications', function(config) { 11 + 12 + var root = JX.$(config.listID); 13 + 14 + var list = new JX.DraggableList('pinned-application', root) 15 + .setFindItemsHandler(function() { 16 + return JX.DOM.scry(root, 'li', 'pinned-application'); 17 + }); 18 + 19 + list.listen('didDrop', function(node, after) { 20 + var nodes = list.findItems(); 21 + var order = []; 22 + var key; 23 + for (var ii = 0; ii < nodes.length; ii++) { 24 + key = JX.Stratcom.getData(nodes[ii]).applicationClass; 25 + if (key) { 26 + order.push(key); 27 + } 28 + } 29 + 30 + list.lock(); 31 + JX.DOM.alterClass(node, 'drag-sending', true); 32 + 33 + new JX.Workflow(config.panelURI, {order: order.join()}) 34 + .start(); 35 + }); 36 + 37 + });