From 3c7944d297b2416d568ca2a7ab1e5c212adb78ff Mon Sep 17 00:00:00 2001 From: epriestley Date: Mon, 30 Jul 2012 16:09:14 -0700 Subject: [PATCH] Switch to new menubar Summary: - Looks better (can probably still use some tweaks), especially search. - Moves logout from weird footer location to main menu. - Reactive: on tablets and phones, the menu adjusts to remain useful. - Fixed position on desktops for future side nav changes. - Adds an icon header thing that's currently hard-coded but will be application-driven soon. Test Plan: Used menu on desktop, tablet, phone, logged in / logged out, toggled darkconsole. Will add some screenshots. Reviewers: btrahan, chad Reviewed By: btrahan CC: aran Maniphest Tasks: T1569 Differential Revision: https://secure.phabricator.com/D3105 --- src/__celerity_resource_map__.php | 146 ++++++--- src/__phutil_library_map__.php | 8 + .../view/DifferentialChangesetListView.php | 4 +- .../constants/PhabricatorSearchScope.php | 15 + src/view/page/AphrontPageView.php | 4 +- src/view/page/PhabricatorStandardPageView.php | 247 ++++++-------- .../menu/PhabricatorMainMenuGroupView.php | 55 ++++ .../page/menu/PhabricatorMainMenuIconView.php | 79 +++++ .../menu/PhabricatorMainMenuSearchView.php | 90 ++++++ .../page/menu/PhabricatorMainMenuView.php | 149 +++++++++ webroot/rsrc/css/application/base/glyph.css | 28 +- .../css/application/base/main-menu-view.css | 301 ++++++++++++++++++ .../application/base/notification-menu.css | 52 +++ .../application/base/standard-page-view.css | 187 +---------- webroot/rsrc/image/bolt.png | Bin 0 -> 351 bytes webroot/rsrc/image/lines.png | Bin 0 -> 2816 bytes webroot/rsrc/image/logo_grey.png | Bin 0 -> 1765 bytes webroot/rsrc/image/search.png | Bin 0 -> 276 bytes .../aphlict/behavior-aphlict-dropdown.js | 17 +- .../aphlict/behavior-aphlict-listen.js | 5 +- .../core/behavior-keyboard-shortcuts.js | 20 +- 21 files changed, 988 insertions(+), 419 deletions(-) create mode 100644 src/view/page/menu/PhabricatorMainMenuGroupView.php create mode 100644 src/view/page/menu/PhabricatorMainMenuIconView.php create mode 100644 src/view/page/menu/PhabricatorMainMenuSearchView.php create mode 100644 src/view/page/menu/PhabricatorMainMenuView.php create mode 100644 webroot/rsrc/css/application/base/main-menu-view.css create mode 100644 webroot/rsrc/css/application/base/notification-menu.css create mode 100644 webroot/rsrc/image/bolt.png create mode 100644 webroot/rsrc/image/lines.png create mode 100644 webroot/rsrc/image/logo_grey.png create mode 100644 webroot/rsrc/image/search.png diff --git a/src/__celerity_resource_map__.php b/src/__celerity_resource_map__.php index eedb81c8e7..7215e7f21c 100644 --- a/src/__celerity_resource_map__.php +++ b/src/__celerity_resource_map__.php @@ -21,6 +21,13 @@ celerity_register_resource_map(array( 'disk' => '/rsrc/image/avatar.png', 'type' => 'png', ), + '/rsrc/image/bolt.png' => + array( + 'hash' => 'f8c30376f30cf5a8675a5e683400684a', + 'uri' => '/res/f8c30376/rsrc/image/bolt.png', + 'disk' => '/rsrc/image/bolt.png', + 'type' => 'png', + ), '/rsrc/image/credit_cards.png' => array( 'hash' => '681448de424ea159b6ea68af04c046ae', @@ -343,6 +350,20 @@ celerity_register_resource_map(array( 'disk' => '/rsrc/image/icon/unsubscribe.png', 'type' => 'png', ), + '/rsrc/image/lines.png' => + array( + 'hash' => '0eb5778b34dd4fcee53b9924b88e0828', + 'uri' => '/res/0eb5778b/rsrc/image/lines.png', + 'disk' => '/rsrc/image/lines.png', + 'type' => 'png', + ), + '/rsrc/image/logo_grey.png' => + array( + 'hash' => '6cff2a21538eeae471f0ea00cb7bc15d', + 'uri' => '/res/6cff2a21/rsrc/image/logo_grey.png', + 'disk' => '/rsrc/image/logo_grey.png', + 'type' => 'png', + ), '/rsrc/image/notification_menu.png' => array( 'hash' => 'f3834ad08a16fc631cd46ceb5db4fb0e', @@ -371,6 +392,13 @@ celerity_register_resource_map(array( 'disk' => '/rsrc/image/phabricator_logo_admin.png', 'type' => 'png', ), + '/rsrc/image/search.png' => + array( + 'hash' => '8c9b0f3000081c1322cd45c4e1b2260c', + 'uri' => '/res/8c9b0f30/rsrc/image/search.png', + 'disk' => '/rsrc/image/search.png', + 'type' => 'png', + ), '/rsrc/image/sprite.png' => array( 'hash' => '8c6200d3191c0deea30f22e7b8166b15', @@ -758,7 +786,7 @@ celerity_register_resource_map(array( ), 'javelin-behavior-aphlict-dropdown' => array( - 'uri' => '/res/425c08fd/rsrc/js/application/aphlict/behavior-aphlict-dropdown.js', + 'uri' => '/res/dc8f194b/rsrc/js/application/aphlict/behavior-aphlict-dropdown.js', 'type' => 'js', 'requires' => array( @@ -772,7 +800,7 @@ celerity_register_resource_map(array( ), 'javelin-behavior-aphlict-listen' => array( - 'uri' => '/res/c716b386/rsrc/js/application/aphlict/behavior-aphlict-listen.js', + 'uri' => '/res/0743d3f3/rsrc/js/application/aphlict/behavior-aphlict-listen.js', 'type' => 'js', 'requires' => array( @@ -1349,7 +1377,7 @@ celerity_register_resource_map(array( ), 'javelin-behavior-phabricator-keyboard-shortcuts' => array( - 'uri' => '/res/06a151d8/rsrc/js/application/core/behavior-keyboard-shortcuts.js', + 'uri' => '/res/c5eb65cd/rsrc/js/application/core/behavior-keyboard-shortcuts.js', 'type' => 'js', 'requires' => array( @@ -1462,7 +1490,7 @@ celerity_register_resource_map(array( ), 'javelin-behavior-placeholder' => array( - 'uri' => '/res/85f097cb/rsrc/js/application/core/behavior-placeholder.js', + 'uri' => '/res/7dc26990/rsrc/js/application/core/behavior-placeholder.js', 'type' => 'js', 'requires' => array( @@ -2178,7 +2206,7 @@ celerity_register_resource_map(array( ), 'phabricator-glyph-css' => array( - 'uri' => '/res/52f0dc90/rsrc/css/application/base/glyph.css', + 'uri' => '/res/1c8a36a8/rsrc/css/application/base/glyph.css', 'type' => 'css', 'requires' => array( @@ -2220,6 +2248,15 @@ celerity_register_resource_map(array( ), 'disk' => '/rsrc/js/application/core/KeyboardShortcutManager.js', ), + 'phabricator-main-menu-view' => + array( + 'uri' => '/res/1475552c/rsrc/css/application/base/main-menu-view.css', + 'type' => 'css', + 'requires' => + array( + ), + 'disk' => '/rsrc/css/application/base/main-menu-view.css', + ), 'phabricator-menu-item' => array( 'uri' => '/res/32fc2325/rsrc/js/application/core/DropdownMenuItem.js', @@ -2253,6 +2290,15 @@ celerity_register_resource_map(array( ), 'disk' => '/rsrc/css/aphront/notification.css', ), + 'phabricator-notification-menu-css' => + array( + 'uri' => '/res/fc8a7fb9/rsrc/css/application/base/notification-menu.css', + 'type' => 'css', + 'requires' => + array( + ), + 'disk' => '/rsrc/css/application/base/notification-menu.css', + ), 'phabricator-object-selector-css' => array( 'uri' => '/res/7eb4c705/rsrc/css/application/objectselector/object-selector.css', @@ -2364,7 +2410,7 @@ celerity_register_resource_map(array( ), 'phabricator-standard-page-view' => array( - 'uri' => '/res/48118f6f/rsrc/css/application/base/standard-page-view.css', + 'uri' => '/res/4c0444c2/rsrc/css/application/base/standard-page-view.css', 'type' => 'css', 'requires' => array( @@ -2619,7 +2665,7 @@ celerity_register_resource_map(array( ), array( 'packages' => array( - '12ecfc95' => + 'abce9c99' => array( 'name' => 'core.pkg.css', 'symbols' => @@ -2648,10 +2694,10 @@ celerity_register_resource_map(array( 21 => 'phabricator-flag-css', 22 => 'aphront-error-view-css', ), - 'uri' => '/res/pkg/12ecfc95/core.pkg.css', + 'uri' => '/res/pkg/abce9c99/core.pkg.css', 'type' => 'css', ), - 'f363b322' => + '971b021e' => array( 'name' => 'core.pkg.js', 'symbols' => @@ -2674,7 +2720,7 @@ celerity_register_resource_map(array( 15 => 'javelin-behavior-phabricator-tooltips', 16 => 'phabricator-prefab', ), - 'uri' => '/res/pkg/f363b322/core.pkg.js', + 'uri' => '/res/pkg/971b021e/core.pkg.js', 'type' => 'js', ), '96bc37d6' => @@ -2815,20 +2861,20 @@ celerity_register_resource_map(array( 'reverse' => array( 'aphront-attached-file-view-css' => '7839ae2d', - 'aphront-crumbs-view-css' => '12ecfc95', - 'aphront-dialog-view-css' => '12ecfc95', - 'aphront-error-view-css' => '12ecfc95', - 'aphront-form-view-css' => '12ecfc95', + 'aphront-crumbs-view-css' => 'abce9c99', + 'aphront-dialog-view-css' => 'abce9c99', + 'aphront-error-view-css' => 'abce9c99', + 'aphront-form-view-css' => 'abce9c99', 'aphront-headsup-action-list-view-css' => '96bc37d6', - 'aphront-headsup-view-css' => '12ecfc95', - 'aphront-list-filter-view-css' => '12ecfc95', - 'aphront-pager-view-css' => '12ecfc95', - 'aphront-panel-view-css' => '12ecfc95', - 'aphront-side-nav-view-css' => '12ecfc95', - 'aphront-table-view-css' => '12ecfc95', - 'aphront-tokenizer-control-css' => '12ecfc95', - 'aphront-tooltip-css' => '12ecfc95', - 'aphront-typeahead-control-css' => '12ecfc95', + 'aphront-headsup-view-css' => 'abce9c99', + 'aphront-list-filter-view-css' => 'abce9c99', + 'aphront-pager-view-css' => 'abce9c99', + 'aphront-panel-view-css' => 'abce9c99', + 'aphront-side-nav-view-css' => 'abce9c99', + 'aphront-table-view-css' => 'abce9c99', + 'aphront-tokenizer-control-css' => 'abce9c99', + 'aphront-tooltip-css' => 'abce9c99', + 'aphront-typeahead-control-css' => 'abce9c99', 'differential-changeset-view-css' => '96bc37d6', 'differential-core-view-css' => '96bc37d6', 'differential-inline-comment-editor' => 'f4bbbd84', @@ -2846,7 +2892,7 @@ celerity_register_resource_map(array( 'javelin-behavior-aphront-basic-tokenizer' => '97f65640', 'javelin-behavior-aphront-drag-and-drop' => 'f4bbbd84', 'javelin-behavior-aphront-drag-and-drop-textarea' => 'f4bbbd84', - 'javelin-behavior-aphront-form-disable-on-submit' => 'f363b322', + 'javelin-behavior-aphront-form-disable-on-submit' => '971b021e', 'javelin-behavior-audit-preview' => '5e68be89', 'javelin-behavior-buoyant' => 'f4bbbd84', 'javelin-behavior-differential-accept-with-errors' => 'f4bbbd84', @@ -2866,20 +2912,20 @@ celerity_register_resource_map(array( 'javelin-behavior-maniphest-transaction-controls' => '7707de41', 'javelin-behavior-maniphest-transaction-expand' => '7707de41', 'javelin-behavior-maniphest-transaction-preview' => '7707de41', - 'javelin-behavior-phabricator-autofocus' => 'f363b322', - 'javelin-behavior-phabricator-keyboard-shortcuts' => 'f363b322', + 'javelin-behavior-phabricator-autofocus' => '971b021e', + 'javelin-behavior-phabricator-keyboard-shortcuts' => '971b021e', 'javelin-behavior-phabricator-object-selector' => 'f4bbbd84', - 'javelin-behavior-phabricator-oncopy' => 'f363b322', - 'javelin-behavior-phabricator-tooltips' => 'f363b322', - 'javelin-behavior-phabricator-watch-anchor' => 'f363b322', - 'javelin-behavior-refresh-csrf' => 'f363b322', + 'javelin-behavior-phabricator-oncopy' => '971b021e', + 'javelin-behavior-phabricator-tooltips' => '971b021e', + 'javelin-behavior-phabricator-watch-anchor' => '971b021e', + 'javelin-behavior-refresh-csrf' => '971b021e', 'javelin-behavior-repository-crossreference' => 'f4bbbd84', - 'javelin-behavior-workflow' => 'f363b322', + 'javelin-behavior-workflow' => '971b021e', 'javelin-dom' => '6fb20113', 'javelin-event' => '6fb20113', 'javelin-install' => '6fb20113', 'javelin-json' => '6fb20113', - 'javelin-mask' => 'f363b322', + 'javelin-mask' => '971b021e', 'javelin-request' => '6fb20113', 'javelin-stratcom' => '6fb20113', 'javelin-tokenizer' => '97f65640', @@ -2891,30 +2937,30 @@ celerity_register_resource_map(array( 'javelin-uri' => '6fb20113', 'javelin-util' => '6fb20113', 'javelin-vector' => '6fb20113', - 'javelin-workflow' => 'f363b322', + 'javelin-workflow' => '971b021e', 'maniphest-task-summary-css' => '7839ae2d', 'maniphest-transaction-detail-css' => '7839ae2d', - 'phabricator-app-buttons-css' => '12ecfc95', + 'phabricator-app-buttons-css' => 'abce9c99', 'phabricator-content-source-view-css' => '96bc37d6', - 'phabricator-core-buttons-css' => '12ecfc95', - 'phabricator-core-css' => '12ecfc95', - 'phabricator-directory-css' => '12ecfc95', + 'phabricator-core-buttons-css' => 'abce9c99', + 'phabricator-core-css' => 'abce9c99', + 'phabricator-directory-css' => 'abce9c99', 'phabricator-drag-and-drop-file-upload' => 'f4bbbd84', - 'phabricator-dropdown-menu' => 'f363b322', - 'phabricator-flag-css' => '12ecfc95', - 'phabricator-jump-nav' => '12ecfc95', - 'phabricator-keyboard-shortcut' => 'f363b322', - 'phabricator-keyboard-shortcut-manager' => 'f363b322', - 'phabricator-menu-item' => 'f363b322', + 'phabricator-dropdown-menu' => '971b021e', + 'phabricator-flag-css' => 'abce9c99', + 'phabricator-jump-nav' => 'abce9c99', + 'phabricator-keyboard-shortcut' => '971b021e', + 'phabricator-keyboard-shortcut-manager' => '971b021e', + 'phabricator-menu-item' => '971b021e', 'phabricator-object-selector-css' => '96bc37d6', - 'phabricator-paste-file-upload' => 'f363b322', - 'phabricator-prefab' => 'f363b322', + 'phabricator-paste-file-upload' => '971b021e', + 'phabricator-prefab' => '971b021e', 'phabricator-project-tag-css' => '7839ae2d', - 'phabricator-remarkup-css' => '12ecfc95', + 'phabricator-remarkup-css' => 'abce9c99', 'phabricator-shaped-request' => 'f4bbbd84', - 'phabricator-standard-page-view' => '12ecfc95', - 'phabricator-tooltip' => 'f363b322', - 'phabricator-transaction-view-css' => '12ecfc95', - 'syntax-highlighting-css' => '12ecfc95', + 'phabricator-standard-page-view' => 'abce9c99', + 'phabricator-tooltip' => '971b021e', + 'phabricator-transaction-view-css' => 'abce9c99', + 'syntax-highlighting-css' => 'abce9c99', ), )); diff --git a/src/__phutil_library_map__.php b/src/__phutil_library_map__.php index 0de8f96484..2b4101d396 100644 --- a/src/__phutil_library_map__.php +++ b/src/__phutil_library_map__.php @@ -752,6 +752,10 @@ phutil_register_library_map(array( 'PhabricatorMailImplementationSendGridAdapter' => 'applications/metamta/adapter/PhabricatorMailImplementationSendGridAdapter.php', 'PhabricatorMailImplementationTestAdapter' => 'applications/metamta/adapter/PhabricatorMailImplementationTestAdapter.php', 'PhabricatorMailReplyHandler' => 'applications/metamta/replyhandler/PhabricatorMailReplyHandler.php', + 'PhabricatorMainMenuGroupView' => 'view/page/menu/PhabricatorMainMenuGroupView.php', + 'PhabricatorMainMenuIconView' => 'view/page/menu/PhabricatorMainMenuIconView.php', + 'PhabricatorMainMenuSearchView' => 'view/page/menu/PhabricatorMainMenuSearchView.php', + 'PhabricatorMainMenuView' => 'view/page/menu/PhabricatorMainMenuView.php', 'PhabricatorMarkupCache' => 'applications/cache/storage/PhabricatorMarkupCache.php', 'PhabricatorMarkupEngine' => 'infrastructure/markup/PhabricatorMarkupEngine.php', 'PhabricatorMarkupInterface' => 'infrastructure/markup/PhabricatorMarkupInterface.php', @@ -1781,6 +1785,10 @@ phutil_register_library_map(array( 'PhabricatorMailImplementationPHPMailerLiteAdapter' => 'PhabricatorMailImplementationAdapter', 'PhabricatorMailImplementationSendGridAdapter' => 'PhabricatorMailImplementationAdapter', 'PhabricatorMailImplementationTestAdapter' => 'PhabricatorMailImplementationAdapter', + 'PhabricatorMainMenuGroupView' => 'AphrontView', + 'PhabricatorMainMenuIconView' => 'AphrontView', + 'PhabricatorMainMenuSearchView' => 'AphrontView', + 'PhabricatorMainMenuView' => 'AphrontView', 'PhabricatorMarkupCache' => 'PhabricatorCacheDAO', 'PhabricatorMetaMTAController' => 'PhabricatorController', 'PhabricatorMetaMTADAO' => 'PhabricatorLiskDAO', diff --git a/src/applications/differential/view/DifferentialChangesetListView.php b/src/applications/differential/view/DifferentialChangesetListView.php index 289dd23ff7..7d3005ecb1 100644 --- a/src/applications/differential/view/DifferentialChangesetListView.php +++ b/src/applications/differential/view/DifferentialChangesetListView.php @@ -110,7 +110,9 @@ final class DifferentialChangesetListView extends AphrontView { $changesets = $this->changesets; - Javelin::initBehavior('buoyant', array()); + // TODO: Restore this once we make it through the redesign, it has funky + // interactions with things and there are various reports that it's slow. + // Javelin::initBehavior('buoyant', array()); Javelin::initBehavior('differential-toggle-files', array()); diff --git a/src/applications/search/constants/PhabricatorSearchScope.php b/src/applications/search/constants/PhabricatorSearchScope.php index 0ac4f7603d..240c578737 100644 --- a/src/applications/search/constants/PhabricatorSearchScope.php +++ b/src/applications/search/constants/PhabricatorSearchScope.php @@ -37,4 +37,19 @@ final class PhabricatorSearchScope { ); } + public static function getScopePlaceholder($scope) { + switch ($scope) { + case self::SCOPE_OPEN_TASKS: + return pht('Search Open Tasks'); + case self::SCOPE_WIKI: + return pht('Search Wiki Documents'); + case self::SCOPE_OPEN_REVISIONS: + return pht('Search Open Revisions'); + case self::SCOPE_COMMITS: + return pht('Search Commits'); + default: + return pht('Search'); + } + } + } diff --git a/src/view/page/AphrontPageView.php b/src/view/page/AphrontPageView.php index a064cb29c7..3a1582ee2a 100644 --- a/src/view/page/AphrontPageView.php +++ b/src/view/page/AphrontPageView.php @@ -62,9 +62,11 @@ abstract class AphrontPageView extends AphrontView { $this->willRenderPage(); $title = phutil_escape_html($this->getTitle()); - $head = $this->getHead(); $body = $this->getBody(); $tail = $this->getTail(); + // NOTE: Render HEAD last so we can pick up resources required by the other + // parts. + $head = $this->getHead(); $body_classes = $this->getBodyClasses(); diff --git a/src/view/page/PhabricatorStandardPageView.php b/src/view/page/PhabricatorStandardPageView.php index c7f2fb077f..2ba94e5989 100644 --- a/src/view/page/PhabricatorStandardPageView.php +++ b/src/view/page/PhabricatorStandardPageView.php @@ -149,9 +149,6 @@ final class PhabricatorStandardPageView extends AphrontPageView { require_celerity_resource('phabricator-core-css'); require_celerity_resource('phabricator-core-buttons-css'); require_celerity_resource('phabricator-standard-page-view'); - if (PhabricatorEnv::getEnvConfig('notification.enabled')) { - require_celerity_resource('phabricator-notification-css'); - } $current_token = null; $request = $this->getRequest(); @@ -172,19 +169,6 @@ final class PhabricatorStandardPageView extends AphrontPageView { 'current' => $current_token, )); - $pref_shortcut = PhabricatorUserPreferences::PREFERENCE_SEARCH_SHORTCUT; - if ($user) { - $shortcut = $user->loadPreferences()->getPreference($pref_shortcut, 1); - } else { - $shortcut = 1; - } - Javelin::initBehavior( - 'phabricator-keyboard-shortcuts', - array( - 'helpURI' => '/help/keyboardshortcut/', - 'search_shortcut' => $shortcut, - )); - if ($console) { require_celerity_resource('aphront-dark-console-css'); Javelin::initBehavior( @@ -317,7 +301,12 @@ final class PhabricatorStandardPageView extends AphrontPageView { 'method' => 'post', 'style' => 'display: inline', ), - ''. + ''. ' in '. AphrontFormSelectControl::renderSelectTag( $this->getSearchDefaultScope(), @@ -362,19 +351,6 @@ final class PhabricatorStandardPageView extends AphrontPageView { $foot_links[] = $link; } - if ($user && $user->getPHID()) { - // This ends up very early in tab order at the top of the page and there's - // a bunch of junk up there anyway, just shove it down here. - $foot_links[] = phabricator_render_form( - $user, - array( - 'action' => '/logout/', - 'method' => 'post', - 'style' => 'display: inline', - ), - ''); - } - $foot_links = implode(' · ', $foot_links); $admin_class = null; @@ -382,119 +358,10 @@ final class PhabricatorStandardPageView extends AphrontPageView { $admin_class = 'phabricator-admin-page-view'; } - $notification_indicator = ''; - $notification_dropdown = ''; - $notification_container = ''; - - if (PhabricatorEnv::getEnvConfig('notification.enabled') && - $user && - $user->isLoggedIn()) { - - $aphlict_object_id = 'aphlictswfobject'; - - $client_uri = PhabricatorEnv::getEnvConfig('notification.client-uri'); - $client_uri = new PhutilURI($client_uri); - if ($client_uri->getDomain() == 'localhost') { - $this_host = $this->getRequest()->getHost(); - $this_host = new PhutilURI('http://'.$this_host.'/'); - $client_uri->setDomain($this_host->getDomain()); - } - - $enable_debug = PhabricatorEnv::getEnvConfig('notification.debug'); - - Javelin::initBehavior( - 'aphlict-listen', - array( - 'id' => $aphlict_object_id, - 'server' => $client_uri->getDomain(), - 'port' => $client_uri->getPort(), - 'debug' => $enable_debug, - 'pageObjects' => array_fill_keys($this->pageObjects, true), - )); - - Javelin::initBehavior('aphlict-dropdown', array()); - - $notification_count = id(new PhabricatorFeedStoryNotification()) - ->countUnread($user); - - $indicator_classes = array( - 'phabricator-notification-indicator', - ); - if ($notification_count) { - $indicator_classes[] = 'phabricator-notification-indicator-unread'; - } - - $notification_indicator = javelin_render_tag( - 'div', - array( - 'id' => 'phabricator-notification-indicator', - 'class' => implode(' ', $indicator_classes), - ), - $notification_count); - - $notification_indicator = javelin_render_tag( - 'div', - array( - 'id' => 'phabricator-notification-menu', - 'class' => 'phabricator-icon-menu icon-menu-notifications', - 'sigil' => 'aphlict-indicator', - ), - $notification_indicator); - - $notification_indicator = javelin_render_tag( - 'td', - array( - 'class' => 'phabricator-icon-menu-cell', - ), - $notification_indicator); - - $notification_container = - '
'. - '
'; - $notification_dropdown = - javelin_render_tag( - 'div', - array( - 'sigil' => 'aphlict-dropdown', - 'id' => 'phabricator-notification-dropdown', - 'style' => 'display: none', - ), - ''); - } - $header_chrome = null; $footer_chrome = null; if ($this->getShowChrome()) { - $header_chrome = - ''. - ''. - ''. - $notification_indicator. - ''. - ''. - ''. - '
'. - ''. - ''. - ''. - $tabs. - ''. - '
'. - phutil_render_tag( - 'a', - array( - 'href' => $this->getBaseURI(), - 'class' => 'phabricator-head-appname', - ), - phutil_escape_html($this->getApplicationName())). - '
'. - '
'. - $notification_dropdown. - $notification_container; + $header_chrome = $this->renderMainMenu(); $footer_chrome = '
'. $foot_links. @@ -531,8 +398,6 @@ final class PhabricatorStandardPageView extends AphrontPageView { $classes = implode(' ', $classes); return - ($console ? '' : null). - $developer_warning. phutil_render_tag( 'div', array( @@ -540,15 +405,58 @@ final class PhabricatorStandardPageView extends AphrontPageView { 'class' => $classes, ), $header_chrome. - $this->bodyContent. - '
'). + '
'. + ($console ? '' : null). + $developer_warning. + $this->bodyContent. + '
'. + '
'). $footer_chrome; } protected function getTail() { + $request = $this->getRequest(); + $user = $request->getUser(); + + $container = null; + if (PhabricatorEnv::getEnvConfig('notification.enabled') && + $user->isLoggedIn()) { + + $aphlict_object_id = celerity_generate_unique_node_id(); + $aphlict_container_id = celerity_generate_unique_node_id(); + + $client_uri = PhabricatorEnv::getEnvConfig('notification.client-uri'); + $client_uri = new PhutilURI($client_uri); + if ($client_uri->getDomain() == 'localhost') { + $this_host = $this->getRequest()->getHost(); + $this_host = new PhutilURI('http://'.$this_host.'/'); + $client_uri->setDomain($this_host->getDomain()); + } + + $enable_debug = PhabricatorEnv::getEnvConfig('notification.debug'); + Javelin::initBehavior( + 'aphlict-listen', + array( + 'id' => $aphlict_object_id, + 'containerID' => $aphlict_container_id, + 'server' => $client_uri->getDomain(), + 'port' => $client_uri->getPort(), + 'debug' => $enable_debug, + 'pageObjects' => array_fill_keys($this->pageObjects, true), + )); + $container = phutil_render_tag( + 'div', + array( + 'id' => $aphlict_container_id, + 'style' => 'position: absolute; width: 0; height: 0;', + ), + 'asdb'); + } + $response = CelerityAPI::getStaticResourceResponse(); return $response->renderResourcesOfType('js'). + $container. $response->renderHTMLFooter(); } @@ -568,4 +476,55 @@ final class PhabricatorStandardPageView extends AphrontPageView { } return $this->getRequest()->getApplicationConfiguration()->getConsole(); } + + private function renderMainMenu() { + $request = $this->getRequest(); + $user = $request->getUser(); + + $menu = new PhabricatorMainMenuView(); + $menu->setUser($user); + + $keyboard_config = array( + 'helpURI' => '/help/keyboardshortcut/', + ); + + if ($user->isLoggedIn()) { + $search = new PhabricatorMainMenuSearchView(); + $search->setUser($user); + $search->setScope($this->getSearchDefaultScope()); + $menu->appendChild($search); + + $pref_shortcut = PhabricatorUserPreferences::PREFERENCE_SEARCH_SHORTCUT; + if ($user->loadPreferences()->getPreference($pref_shortcut, true)) { + $keyboard_config['searchID'] = $search->getID(); + } + } + + Javelin::initBehavior('phabricator-keyboard-shortcuts', $keyboard_config); + + if ($user->isLoggedIn()) { + require_celerity_resource('phabricator-glyph-css'); + + $item = new PhabricatorMainMenuIconView(); + $item->setName($user->getUsername()); + $item->addClass('glyph glyph-profile'); + $item->setHref('/p/'.$user->getUsername().'/'); + $menu->appendChild($item); + + $item = new PhabricatorMainMenuIconView(); + $item->setName(pht('Settings')); + $item->addClass('glyph glyph-settings'); + $item->setHref('/settings/'); + $menu->appendChild($item); + + $item = new PhabricatorMainMenuIconView(); + $item->setName(pht('Log Out')); + $item->addClass('glyph glyph-logout'); + $item->setHref('/logout/'); + $menu->appendChild($item); + } + + return $menu->render(); + } + } diff --git a/src/view/page/menu/PhabricatorMainMenuGroupView.php b/src/view/page/menu/PhabricatorMainMenuGroupView.php new file mode 100644 index 0000000000..9767f42071 --- /dev/null +++ b/src/view/page/menu/PhabricatorMainMenuGroupView.php @@ -0,0 +1,55 @@ +classes[] = $class; + return $this; + } + + public function setCollapsible($collapsible) { + $this->collapsible = $collapsible; + return $this; + } + + public function render() { + $classes = array( + 'phabricator-main-menu-group', + ); + + if ($this->collapsible) { + $classes[] = 'phabricator-main-menu-collapsible'; + } + + if ($this->classes) { + $classes = array_merge($classes, $this->classes); + } + + return phutil_render_tag( + 'div', + array( + 'class' => implode(' ', $classes), + ), + $this->renderChildren()); + } + +} diff --git a/src/view/page/menu/PhabricatorMainMenuIconView.php b/src/view/page/menu/PhabricatorMainMenuIconView.php new file mode 100644 index 0000000000..8df9fcb697 --- /dev/null +++ b/src/view/page/menu/PhabricatorMainMenuIconView.php @@ -0,0 +1,79 @@ +name = $name; + return $this; + } + + public function getName() { + return $this->name; + } + + public function setHref($href) { + $this->href = $href; + return $this; + } + + public function getHref() { + return $this->href; + } + + public function addClass($class) { + $this->classes[] = $class; + return $this; + } + + + public function render() { + $name = $this->getName(); + $href = $this->getHref(); + + $classes = $this->classes; + $classes[] = 'phabricator-main-menu-icon'; + + $label = javelin_render_tag( + 'a', + array( + 'href' => $href, + 'class' => 'phabricator-main-menu-icon-label', + ), + phutil_escape_html($name)); + + $item = javelin_render_tag( + 'a', + array( + 'href' => $href, + 'class' => implode(' ', $classes), + ), + ''); + + $group = new PhabricatorMainMenuGroupView(); + $group->appendChild($item); + $group->appendChild($label); + + return $group->render(); + } + +} diff --git a/src/view/page/menu/PhabricatorMainMenuSearchView.php b/src/view/page/menu/PhabricatorMainMenuSearchView.php new file mode 100644 index 0000000000..8988fc4bf7 --- /dev/null +++ b/src/view/page/menu/PhabricatorMainMenuSearchView.php @@ -0,0 +1,90 @@ +user = $user; + return $this; + } + + public function setScope($scope) { + $this->scope = $scope; + return $this; + } + + public function getID() { + if (!$this->id) { + $this->id = celerity_generate_unique_node_id(); + } + return $this->id; + } + + public function render() { + $user = $this->user; + + $search_id = $this->getID(); + + $input = phutil_render_tag( + 'input', + array( + 'type' => 'text', + 'name' => 'query', + 'id' => $search_id, + )); + + $scope = $this->scope; + + Javelin::initBehavior( + 'placeholder', + array( + 'id' => $search_id, + 'text' => PhabricatorSearchScope::getScopePlaceholder($scope), + )); + + $scope_input = phutil_render_tag( + 'input', + array( + 'type' => 'hidden', + 'name' => 'scope', + 'value' => $scope, + )); + + $form = phabricator_render_form( + $user, + array( + 'action' => '/search/', + 'method' => 'POST', + ), + '
'. + $input. + ''. + $scope_input. + '
'); + + $group = new PhabricatorMainMenuGroupView(); + $group->addClass('phabricator-main-menu-search'); + $group->appendChild($form); + return $group->render(); + } + +} diff --git a/src/view/page/menu/PhabricatorMainMenuView.php b/src/view/page/menu/PhabricatorMainMenuView.php new file mode 100644 index 0000000000..a0da68dff1 --- /dev/null +++ b/src/view/page/menu/PhabricatorMainMenuView.php @@ -0,0 +1,149 @@ +user = $user; + } + + public function render() { + $user = $this->user; + + require_celerity_resource('phabricator-main-menu-view'); + + $header_id = celerity_generate_unique_node_id(); + $extra = ''; + + $group = new PhabricatorMainMenuGroupView(); + $group->addClass('phabricator-main-menu-group-logo'); + $group->setCollapsible(false); + + $group->appendChild( + phutil_render_tag( + 'a', + array( + 'class' => 'phabricator-main-menu-logo', + 'href' => '/', + ), + 'Phabricator')); + + if (PhabricatorEnv::getEnvConfig('notification.enabled') && + $user->isLoggedIn()) { + list($menu, $dropdown) = $this->renderNotificationMenu(); + $group->appendChild($menu); + $extra .= $dropdown; + } + + $group->appendChild( + javelin_render_tag( + 'a', + array( + 'class' => 'phabricator-main-menu-expand-button', + 'sigil' => 'jx-toggle-class', + 'meta' => array( + 'map' => array( + $header_id => 'phabricator-main-menu-reveal', + ), + ), + ), + 'Expand')); + $logo = $group->render(); + + return phutil_render_tag( + 'div', + array( + 'class' => 'phabricator-main-menu', + 'id' => $header_id, + ), + $logo.$this->renderChildren()). + $extra; + } + + private function renderNotificationMenu() { + $user = $this->user; + + require_celerity_resource('phabricator-notification-css'); + require_celerity_resource('phabricator-notification-menu-css'); + + $indicator_id = celerity_generate_unique_node_id(); + $dropdown_id = celerity_generate_unique_node_id(); + $menu_id = celerity_generate_unique_node_id(); + + $notification_count = id(new PhabricatorFeedStoryNotification()) + ->countUnread($user); + + $classes = array( + 'phabricator-main-menu-alert-indicator', + ); + if ($notification_count) { + $classes[] = 'phabricator-main-menu-alert-indicator-unread'; + } + + $notification_indicator = javelin_render_tag( + 'span', + array( + 'id' => $indicator_id, + 'class' => implode(' ', $classes), + ), + $notification_count); + + $classes = array(); + $classes[] = 'phabricator-main-menu-alert-item'; + $classes[] = 'phabricator-main-menu-alert-item-notification'; + + $notification_icon = javelin_render_tag( + 'a', + array( + 'href' => '/notification/', + 'class' => implode(' ', $classes), + 'id' => $menu_id, + ), + $notification_indicator); + + $notification_menu = javelin_render_tag( + 'div', + array( + 'class' => 'phabricator-main-menu-alert', + ), + $notification_icon); + + Javelin::initBehavior( + 'aphlict-dropdown', + array( + 'menuID' => $menu_id, + 'indicatorID' => $indicator_id, + 'dropdownID' => $dropdown_id, + )); + + $notification_dropdown = javelin_render_tag( + 'div', + array( + 'id' => $dropdown_id, + 'class' => 'phabricator-notification-menu', + 'sigil' => 'phabricator-notification-menu', + 'style' => 'display: none;', + ), + ''); + + return array($notification_menu, $notification_dropdown); + } + +} diff --git a/webroot/rsrc/css/application/base/glyph.css b/webroot/rsrc/css/application/base/glyph.css index d6e45cea19..9c2d8ffa9d 100644 --- a/webroot/rsrc/css/application/base/glyph.css +++ b/webroot/rsrc/css/application/base/glyph.css @@ -13,61 +13,61 @@ } .glyph-profile-active { - background-position: 0 -56px; + background-position: 0 -28px; } .glyph-profile:hover { - background-position: 0 -112px; + background-position: 0 -56px; } .glyph-settings { - background-position: -56px 0; + background-position: -28px 0; } .glyph-settings-active { - background-position: -56px -56px; + background-position: -28px -28px; } .glyph-settings:hover { - background-position: -56px -112px; + background-position: -28px -56px; } .glyph-logout { - background-position: -112px 0; + background-position: -56px 0; } .glyph-logout-active { - background-position: -112px -56px; + background-position: -56px -28px; } .glyph-logout:hover { - background-position: -112px -112px; + background-position: -56px -56px; } .glyph-notification { - background-position: -168px 0; + background-position: -84px 0; } .glyph-notification-active { - background-position: -168px -56px; + background-position: -84px -28px; } .glyph-notification:hover { - background-position: -168px -112px; + background-position: -84px -56px; } .glyph-menu { - background-position: -224px 0; + background-position: -112px 0; } .glyph-menu-active { - background-position: -224px -56px; + background-position: -112px -28px; } .glyph-menu:hover { - background-position: -224px -112px; + background-position: -112px -56px; } diff --git a/webroot/rsrc/css/application/base/main-menu-view.css b/webroot/rsrc/css/application/base/main-menu-view.css new file mode 100644 index 0000000000..52a7742a3b --- /dev/null +++ b/webroot/rsrc/css/application/base/main-menu-view.css @@ -0,0 +1,301 @@ +/** + * @provides phabricator-main-menu-view + */ + + +/* - Main Menu ----------------------------------------------------------------- + + Main menu at the top of every page that has chrome. It reacts to resolution + changes in order to behave reasonably on tablets and phones. + +*/ + +.phabricator-main-menu { + background: #33393d; + position: relative; + box-shadow: 0px 1px 1px rgba(0, 0, 0, 0.25); + overflow: hidden; + height: 44px; +} + +.phabricator-main-menu a:hover { + text-decoration: none; +} + +.device-desktop .phabricator-main-menu { + text-align: right; + padding-right: 12px; + position: fixed; + width: 100%; + z-index: 6; + top: 0; +} + +.device-desktop .phabricator-standard-page-body { + margin-top: 44px; +} + + +/* - Main Menu Group ----------------------------------------------------------- + + Container representing a single item on the main menu. For desktops these lay + out horizontally; on phones they switch to vertical. + +*/ + +.device-desktop .phabricator-main-menu-group { + display: inline-block; + text-align: left; + height: 44px; +} + +.device-tablet .phabricator-main-menu-group, +.device-phone .phabricator-main-menu-group { + clear: both; + width: 100%; + overflow: hidden; + border-bottom: 1px solid #33393d; + display: block; +} + + +/* - Logo ---------------------------------------------------------------------- + + The "Phabricator" logo group in the main menu. On tablet and phone devices, + this shows a "reveal" button to expand/collapse the rest of the menu. + +*/ + +.phabricator-main-menu-group-logo { + float: left; +} + +.phabricator-main-menu-logo { + display: inline-block; + height: 44px; + width: 180px; + margin-right: 12px; + background: 12px 9px url(/rsrc/image/logo_grey.png) no-repeat; +} + +.phabricator-main-menu-logo span { + display: none; +} + + +/* - Expand/Collapse Button ---------------------------------------------------- + + On phones, the menu switches to a vertical layout and uses a button to expand + or collapse the items. + +*/ + +.phabricator-main-menu-expand-button { + position: absolute; + right: 10px; + top: 10px; + display: block; + width: 40px; + height: 28px; + text-align: center; + background: #22292d url(/rsrc/image/lines.png) no-repeat 8px 6px; + border-radius: 6px; + + border: 1px solid #111111; + box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.1), + 0 1px 0 rgba(255, 255, 255, 0.075); +} + +.device-desktop .phabricator-main-menu-expand-button { + display: none; +} + +.device-tablet .phabricator-main-menu-expand-button, +.device-phone .phabricator-main-menu-expand-button { + display: block; +} + +.phabricator-main-menu-expand-button span { + display: none; +} + +.phabricator-main-menu-reveal .phabricator-main-menu-expand-button { + background-color: #55595d; +} + + +/* - Icon Menus ---------------------------------------------------------------- + + These are the small icons for actions like "Settings" and "Log Out" which + appear on the right side of the main menu. On tablets and phones these layout + vertically. + +*/ + +.phabricator-main-menu-icon { + width: 26px; + height: 26px; + margin: 9px; + display: inline-block; + background-repeat: no-repeat; + position: relative; + overflow: hidden; +} + +.device-desktop .phabricator-main-menu-icon-label { + display: none; +} + +.device-tablet .phabricator-main-menu-icon-label, +.device-phone .phabricator-main-menu-icon-label { + font-weight: bold; + color: #ffffff; + margin-left: 40px; + height: 26px; + margin: 15px 9px 3px 60px; + display: block; +} + +.device-tablet .phabricator-main-menu-icon, +.device-phone .phabricator-main-menu-icon { + font-weight: bold; + color: white; + text-decoration: none; + border: 0; + margin-left: 24px; + position: absolute; +} + + +/* - Search -------------------------------------------------------------------- + + The main search input in the menu bar. + +*/ + +.device-desktop .phabricator-main-menu-search { + width: 220px; +} + +.phabricator-main-menu-search-container { + padding: 10px 0; + position: relative; + height: 24px; +} + +.device-desktop .phabricator-main-menu-search-container { + margin: 0 8px 0 50px; +} + +.device-tablet .phabricator-main-menu-search-container, +.device-phone .phabricator-main-menu-search-container { + margin: 0 18px 0 60px; +} + +.phabricator-main-menu-search input { + outline: 0; + margin: 0; + + width: 100%; + right: 0; + position: absolute; + + border: 1px solid #333333; + border-radius: 12px; + background: #727272; + height: 12px; + line-height: 12px; + box-shadow: 0px 1px 1px rgba(128, 128, 128, 0.25); + padding: 6px 32px 6px 10px; +} + +.phabricator-main-menu-search input:focus { + background: #c9c9c9; +} + +.phabricator-main-menu-search input.jx-placeholder { + color: #aaaaaa; +} + +.phabricator-main-menu-search button { + position: absolute; + color: transparent; + background: transparent 5px 6px url(/rsrc/image/search.png) no-repeat; + border: none; + outline: none; + box-shadow: none; + + height: 20px; + width: 20px; + top: 11px; + right: 6px; +} + + +/* - Collapsible --------------------------------------------------------------- + + By default, groups are collapsible, which means they'll be hidden on phones + and respond to the menu toggle button. + +*/ + +.device-tablet .phabricator-main-menu-collapsible, +.device-phone .phabricator-main-menu-collapsible { + background: #44494d; + display: none; +} + +.phabricator-main-menu-reveal { + height: auto; +} + +.device-tablet .phabricator-main-menu-reveal .phabricator-main-menu-collapsible, +.device-phone .phabricator-main-menu-reveal .phabricator-main-menu-collapsible { + display: block; +} + + +/* - Alert --------------------------------------------------------------------- + + Alert menus are like icon menus but don't obey collapse rules. + +*/ + +.phabricator-main-menu-alert { + display: inline-block; + position: relative; +} + +.phabricator-main-menu-alert-item { + width: 26px; + height: 26px; + margin: 9px; + display: block; +} + +.phabricator-main-menu-alert-indicator { + display: none; +} + +.phabricator-main-menu-alert-indicator-unread { + position: absolute; + display: block; + + right: 0px; + top: 2px; + padding: 1px 4px 2px; + + background: #dd3333; + + border: 1px solid #aa0000; + font-size: 11px; + + box-shadow: 0px 0px 6px rgba(255, 255, 255, 0.5); + border-radius: 6px; + font-weight: bold; + color: #ffffff; +} + +.phabricator-main-menu-alert-item-notification { + background: url(/rsrc/image/bolt.png) no-repeat; +} diff --git a/webroot/rsrc/css/application/base/notification-menu.css b/webroot/rsrc/css/application/base/notification-menu.css new file mode 100644 index 0000000000..f72cd950a8 --- /dev/null +++ b/webroot/rsrc/css/application/base/notification-menu.css @@ -0,0 +1,52 @@ +/** + * @provides phabricator-notification-menu-css + */ + +.phabricator-notification-menu { + background: #ffffff; + font-size: 11px; + word-wrap: break-word; + overflow-y: auto; +} + +.device-desktop .phabricator-notification-menu { + position: fixed; + width: 360px; + top: 42px; + box-shadow: 0px 2px 6px rgba(0, 0, 0, 0.5); + z-index: 9; + + border: 1px solid #33393d; + border-top-width: 0; +} + +.device-tablet .phabricator-notification-menu, +.device-phone .phabricator-notification-menu { + border-bottom: 1px solid #222222; +} + + +.phabricator-notification { + padding: 6px 6px; + margin: 1px 0; +} + +.no-notifications { + color: #999999; +} + +.phabricator-notification-list { + font-size: 11px; +} + +.phabricator-notification-list .phabricator-notification-unread, +.phabricator-notification-menu .phabricator-notification-unread { + background: #aacfef; +} + +.view-all-notifications { + text-align: center; + font-weight: bold; + background: #eeeeee; + border-top: 1px solid #dddddd; +} diff --git a/webroot/rsrc/css/application/base/standard-page-view.css b/webroot/rsrc/css/application/base/standard-page-view.css index 58546d42e9..c2ff90d718 100644 --- a/webroot/rsrc/css/application/base/standard-page-view.css +++ b/webroot/rsrc/css/application/base/standard-page-view.css @@ -2,7 +2,6 @@ * @provides phabricator-standard-page-view */ - .phabricator-standard-page { background: #ffffff; } @@ -10,95 +9,8 @@ .phabricator-chromeless-page .phabricator-standard-page { background: transparent; border-width: 0px; - - -webkit-box-shadow: none; - -mox-box-shadow: none; - box-shadow: none; } -.phabricator-standard-header { - background: #005588; - color: white; - overflow: hidden; - position: relative; - width: 100%; -} - -.phabricator-standard-header td { - vertical-align: bottom; - padding: 0; - margin: 0; -} - -.phabricator-primary-navigation { - padding-top: 24px; - padding-left: 24px; -} - -.phabricator-standard-header a { - color: white; -} - -.phabricator-primary-navigation th, -.phabricator-primary-navigation td { - vertical-align: bottom; - font-size: 13px; - border-bottom: 6px solid transparent; - padding-top: 14px; - padding-bottom: 4px; - white-space: nowrap; -} - -.phabricator-logo { - width: 220px; -} - -.phabricator-logo a { - display: block; - width: 220px; - height: 40px; - padding: 0; - margin: 0; -} - - -.phabricator-logo a.logo-standard { - background: url(/rsrc/image/phabricator_logo.png) no-repeat -220px 0; -} - -.phabricator-admin-page-view .phabricator-logo a.logo-standard { - background-image: url(/rsrc/image/phabricator_logo_admin.png); -} - -.phabricator-logo a.logo-standard:hover { - background-position: -220px -40px; -} - -.phabricator-primary-navigation td { - padding-left: 10px; - padding-right: 10px; -} - -.phabricator-primary-navigation td.phabricator-selected-tab { - border-bottom-color: #ffffff; - background: #336699; -} - - -.phabricator-standard-header .phabricator-head-appname { - padding: 0 1em; - text-transform: uppercase; -} - -td.phabricator-login-details { - text-align: right; - vertical-align: middle; - padding: 0px 24px; - font-size: 12px; - white-space: nowrap; -} - - .phabricator-page-foot { text-align: right; margin: 2em; @@ -108,14 +20,6 @@ td.phabricator-login-details { color: #666666; } -.phabricator-admin-page-view .phabricator-standard-header { - background: #aa0000; -} - -.phabricator-admin-page-view td.phabricator-selected-tab { - background: #cc3333; -} - .keyboard-shortcut-help td, .keyboard-shortcut-help th { padding: 8px; @@ -216,99 +120,10 @@ a.handle-disabled { } -.phabricator-icon-menu { - height: 40px; - width: 60px; - left: -22px; - position: relative; - cursor: pointer; -} - -.phabricator-icon-menu-cell { - width: 60px; -} - -.phabricator-admin-page-view .icon-menu-notifications { - background: url(/rsrc/image/notification_menu_admin.png); -} - -.icon-menu-notifications { - background: url(/rsrc/image/notification_menu.png); -} - -.phabricator-icon-menu:hover { - background-position: 0 -40px; -} - -.phabricator-notification-indicator { - display: none; -} - -.phabricator-notification-indicator-unread { - display: block; - - position: absolute; - right: 8px; - top: 2px; - padding: 1px 3px; - - background: #dd3333; - - border: 1px solid #aa0000; - font-size: 11px; - - box-shadow: 0px 0px 4px rgba(255, 255, 255, 0.75); -} - - -#phabricator-notification-dropdown { - position: absolute; - top: 40px; - - border: 1px solid #99c4d7; - border-top-width: 0; - background: #fdfdff; - - width: 360px; - box-shadow: 0px 1px 3px rgba(0, 0, 0, 0.25); - - font-size: 11px; - - z-index: 3; - - word-wrap: break-word; - overflow-y: auto; -} - -.phabricator-notification { - padding: 6px 6px; - margin: 1px 0; -} - -.no-notifications { - color: #999999; -} - -.phabricator-notification-list { - font-size: 11px; -} - -.phabricator-notification-list .phabricator-notification-unread, -#phabricator-notification-dropdown .phabricator-notification-unread { - background: #aacfef; -} - -.view-all-notifications { - text-align: center; - font-weight: bold; - background: #eeeeee; - border-top: 1px solid #dddddd; -} - - /** * Placeholder text added to inputs by the "placeholder" behavior. */ .jx-placeholder { color: #888888; } + diff --git a/webroot/rsrc/image/bolt.png b/webroot/rsrc/image/bolt.png new file mode 100644 index 0000000000000000000000000000000000000000..1657e6cccbb83d3cab9d8a47712c32ac56eb3252 GIT binary patch literal 351 zcmV-l0igbgP)aih2q*xt02c8DR4G)EfCCP3x>$4onAjdtEyF_9yvLIm z`l(gc>Ep2kRBG^3Gu44Cvq!V!J#y(l6^n5AES_p*9hyP$xC&HiThxypFSN4gJTzY9 x$tcQ5vIt(T(aa)fitDGKaAshnR|66tzyJahvigqI^*#Uq002ovPDHLkV1n?=j57cL literal 0 HcmV?d00001 diff --git a/webroot/rsrc/image/lines.png b/webroot/rsrc/image/lines.png new file mode 100644 index 0000000000000000000000000000000000000000..177a64af0f038d876bc599f8b864f9a6e8b63a97 GIT binary patch literal 2816 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 Hu0mjfAd6rb literal 0 HcmV?d00001 diff --git a/webroot/rsrc/image/search.png b/webroot/rsrc/image/search.png new file mode 100644 index 0000000000000000000000000000000000000000..4bdfef4cd80eb6b752e1514e0f824111a1a75f5a GIT binary patch literal 276 zcmeAS@N?(olHy`uVBq!ia0vp^JRr=$1|-8uW1a&k$r9IylHmNblJdl&R0hYC{G?O` z&)mfH)S%SFl*+=BsWw1G+dN$yLn>}1B{(!NDA=(b`QPwEU0^+Pk}#Xh0``vo&L1-s z_Vpd%cME^RI&}xn5iXBMW)6SYwbUEeJmdtZa7}RQ59;OKjpQ zco1-gY3YAO?spAYM#mQ|' + '' + '' + '' + + 'width="0" height="0" id="' + config.id + '">' + ''; //Evan sanctioned }); diff --git a/webroot/rsrc/js/application/core/behavior-keyboard-shortcuts.js b/webroot/rsrc/js/application/core/behavior-keyboard-shortcuts.js index 24b585ca4c..5c296420da 100644 --- a/webroot/rsrc/js/application/core/behavior-keyboard-shortcuts.js +++ b/webroot/rsrc/js/application/core/behavior-keyboard-shortcuts.js @@ -30,14 +30,14 @@ JX.behavior('phabricator-keyboard-shortcuts', function(config) { }) .register(); - if (config.search_shortcut) { - desc = 'Give keyboard focus to the search box.'; - new JX.KeyboardShortcut('/', desc) - .setHandler(function() { - var search = JX.$("standard-search-box"); - search.focus(); - search.select(); - }) - .register(); - } + if (config.searchID) { + desc = 'Give keyboard focus to the search box.'; + new JX.KeyboardShortcut('/', desc) + .setHandler(function() { + var search = JX.$(config.searchID); + search.focus(); + search.select(); + }) + .register(); + } });