Show avatar at top right in account-dropdown button

* When avatars are enabled, show it instead of full name.
* Port away from 'gr-ajax' for getting server config.
* Cleanup 'gr-rest-api-interface' test a bit.

Change-Id: Ib735a4efee4dd4386885693bc30b55f73a813ec7
diff --git a/polygerrit-ui/app/elements/change/gr-message/gr-message.html b/polygerrit-ui/app/elements/change/gr-message/gr-message.html
index 5733acd..7c287db 100644
--- a/polygerrit-ui/app/elements/change/gr-message/gr-message.html
+++ b/polygerrit-ui/app/elements/change/gr-message/gr-message.html
@@ -19,6 +19,7 @@
 <link rel="import" href="../../shared/gr-button/gr-button.html">
 <link rel="import" href="../../shared/gr-date-formatter/gr-date-formatter.html">
 <link rel="import" href="../../shared/gr-linked-text/gr-linked-text.html">
+<link rel="import" href="../../shared/gr-rest-api-interface/gr-rest-api-interface.html">
 
 <link rel="import" href="../gr-comment-list/gr-comment-list.html">
 
@@ -120,6 +121,7 @@
         <gr-button small on-tap="_handleReplyTap">Reply</gr-button>
       </div>
     </div>
+    <gr-rest-api-interface id="restAPI"></gr-rest-api-interface>
   </template>
   <script src="gr-message.js"></script>
 </dom-module>
diff --git a/polygerrit-ui/app/elements/change/gr-message/gr-message.js b/polygerrit-ui/app/elements/change/gr-message/gr-message.js
index 1ab5e6c..26b9fb9 100644
--- a/polygerrit-ui/app/elements/change/gr-message/gr-message.js
+++ b/polygerrit-ui/app/elements/change/gr-message/gr-message.js
@@ -57,7 +57,7 @@
     },
 
     ready: function() {
-      app.configReady.then(function(cfg) {
+      this.$.restAPI.getConfig().then(function(cfg) {
         this.showAvatar = !!(cfg && cfg.plugin && cfg.plugin.has_avatars) &&
             this.message && this.message.author;
       }.bind(this));
diff --git a/polygerrit-ui/app/elements/core/gr-account-dropdown/gr-account-dropdown.html b/polygerrit-ui/app/elements/core/gr-account-dropdown/gr-account-dropdown.html
index 0d549d9..4538cec 100644
--- a/polygerrit-ui/app/elements/core/gr-account-dropdown/gr-account-dropdown.html
+++ b/polygerrit-ui/app/elements/core/gr-account-dropdown/gr-account-dropdown.html
@@ -17,6 +17,7 @@
 <link rel="import" href="../../../bower_components/polymer/polymer.html">
 <link rel="import" href="../../../bower_components/iron-dropdown/iron-dropdown.html">
 <link rel="import" href="../../shared/gr-button/gr-button.html">
+<link rel="import" href="../../shared/gr-rest-api-interface/gr-rest-api-interface.html">
 
 <dom-module id="gr-account-dropdown">
   <style>
@@ -36,6 +37,11 @@
       font: inherit;
       padding: .3em 0;
     }
+    gr-avatar {
+      height: 1.3em;
+      width: 1.3em;
+      vertical-align: -.25em;
+    }
     ul {
       list-style: none;
     }
@@ -59,7 +65,11 @@
   </style>
   <template>
     <gr-button link class="dropdown-trigger" id="trigger"
-        on-tap="_showDropdownTapHandler">[[account.name]]</gr-button>
+        on-tap="_showDropdownTapHandler">
+      <span hidden$="[[_hasAvatars]]" hidden>[[account.name]]</span>
+      <gr-avatar account="[[account]]" hidden$="[[!_hasAvatars]]" hidden
+          image-size="32"></gr-avatar>
+    </gr-button>
     <iron-dropdown id="dropdown"
         vertical-align="top"
         vertical-offset="25"
@@ -77,6 +87,7 @@
         </ul>
       </div>
     </iron-dropdown>
+    <gr-rest-api-interface id="restAPI"></gr-rest-api-interface>
   </template>
   <script src="gr-account-dropdown.js"></script>
 </dom-module>
diff --git a/polygerrit-ui/app/elements/core/gr-account-dropdown/gr-account-dropdown.js b/polygerrit-ui/app/elements/core/gr-account-dropdown/gr-account-dropdown.js
index 09de6c1..62212a3 100644
--- a/polygerrit-ui/app/elements/core/gr-account-dropdown/gr-account-dropdown.js
+++ b/polygerrit-ui/app/elements/core/gr-account-dropdown/gr-account-dropdown.js
@@ -19,6 +19,13 @@
 
     properties: {
       account: Object,
+      _hasAvatars: Boolean,
+    },
+
+    attached: function() {
+      this.$.restAPI.getConfig().then(function(cfg) {
+        this._hasAvatars = !!(cfg && cfg.plugin && cfg.plugin.has_avatars);
+      }.bind(this));
     },
 
     _showDropdownTapHandler: function(e) {
diff --git a/polygerrit-ui/app/elements/gr-app.html b/polygerrit-ui/app/elements/gr-app.html
index 67ab50f..d7c6c64 100644
--- a/polygerrit-ui/app/elements/gr-app.html
+++ b/polygerrit-ui/app/elements/gr-app.html
@@ -56,7 +56,6 @@
         color: #b71c1c;
       }
     </style>
-    <gr-ajax auto url="/config/server/info" last-response="{{config}}"></gr-ajax>
     <gr-ajax auto url="/config/server/version" last-response="{{version}}"></gr-ajax>
     <gr-ajax id="diffPreferencesXHR"
         url="/accounts/self/preferences.diff"
diff --git a/polygerrit-ui/app/elements/gr-app.js b/polygerrit-ui/app/elements/gr-app.js
index a40e61b..e115d4b 100644
--- a/polygerrit-ui/app/elements/gr-app.js
+++ b/polygerrit-ui/app/elements/gr-app.js
@@ -32,20 +32,7 @@
           }.bind(this));
         },
       },
-      config: {
-        type: Object,
-        observer: '_configChanged',
-      },
-      configReady: {
-        type: Object,
-        readOnly: true,
-        notify: true,
-        value: function() {
-          return new Promise(function(resolve) {
-            this._resolveConfigReady = resolve;
-          }.bind(this));
-        },
-      },
+      config: Object,
       version: String,
       params: Object,
       keyEventTarget: {
@@ -82,6 +69,9 @@
       this.$.restAPI.getAccount().then(function(account) {
         this.account = account;
       }.bind(this));
+      this.$.restAPI.getConfig().then(function(config) {
+        this.config = config;
+      }.bind(this));
     },
 
     ready: function() {
@@ -137,10 +127,6 @@
       }
     },
 
-    _configChanged: function(config) {
-      this._resolveConfigReady(config);
-    },
-
     _viewChanged: function(view) {
       this.set('_showChangeListView', view == 'gr-change-list-view');
       this.set('_showDashboardView', view == 'gr-dashboard-view');
diff --git a/polygerrit-ui/app/elements/shared/gr-avatar/gr-avatar.html b/polygerrit-ui/app/elements/shared/gr-avatar/gr-avatar.html
index 3491443..55655c0 100644
--- a/polygerrit-ui/app/elements/shared/gr-avatar/gr-avatar.html
+++ b/polygerrit-ui/app/elements/shared/gr-avatar/gr-avatar.html
@@ -15,6 +15,7 @@
 -->
 
 <link rel="import" href="../../../bower_components/polymer/polymer.html">
+<link rel="import" href="../gr-rest-api-interface/gr-rest-api-interface.html">
 
 <dom-module id="gr-avatar">
   <template>
@@ -26,6 +27,7 @@
         background-color: var(--background-color, #f1f2f3);
       }
     </style>
+    <gr-rest-api-interface id="restAPI"></gr-rest-api-interface>
   </template>
   <script src="gr-avatar.js"></script>
 </dom-module>
diff --git a/polygerrit-ui/app/elements/shared/gr-avatar/gr-avatar.js b/polygerrit-ui/app/elements/shared/gr-avatar/gr-avatar.js
index 8f289ca..3655975 100644
--- a/polygerrit-ui/app/elements/shared/gr-avatar/gr-avatar.js
+++ b/polygerrit-ui/app/elements/shared/gr-avatar/gr-avatar.js
@@ -32,8 +32,8 @@
       this.hidden = true;
     },
 
-    ready: function() {
-      app.configReady.then(function(cfg) {
+    attached: function() {
+      this.$.restAPI.getConfig().then(function(cfg) {
         var hasAvatars = !!(cfg && cfg.plugin && cfg.plugin.has_avatars);
         if (hasAvatars) {
           this.hidden = false;
diff --git a/polygerrit-ui/app/elements/shared/gr-rest-api-interface/gr-rest-api-interface.js b/polygerrit-ui/app/elements/shared/gr-rest-api-interface/gr-rest-api-interface.js
index 09b6d35..5ac846a 100644
--- a/polygerrit-ui/app/elements/shared/gr-rest-api-interface/gr-rest-api-interface.js
+++ b/polygerrit-ui/app/elements/shared/gr-rest-api-interface/gr-rest-api-interface.js
@@ -82,6 +82,10 @@
       }.bind(this));
     },
 
+    getConfig: function() {
+      return this._fetchSharedCacheURL('/config/server/info');
+    },
+
     getAccount: function() {
       return this._fetchSharedCacheURL('/accounts/self/detail');
     },
diff --git a/polygerrit-ui/app/elements/shared/gr-rest-api-interface/gr-rest-api-interface_test.html b/polygerrit-ui/app/elements/shared/gr-rest-api-interface/gr-rest-api-interface_test.html
index b0a6649..3902707f 100644
--- a/polygerrit-ui/app/elements/shared/gr-rest-api-interface/gr-rest-api-interface_test.html
+++ b/polygerrit-ui/app/elements/shared/gr-rest-api-interface/gr-rest-api-interface_test.html
@@ -42,7 +42,7 @@
       var testJSON = ')]}\'\n{"hello": "bonjour"}';
 
       var fetchStub = sinon.stub(window, 'fetch', function() {
-        return Promise.resolve({ text: function() {
+        return Promise.resolve({text: function() {
           return Promise.resolve(testJSON);
         }});
       });
@@ -65,7 +65,7 @@
 
       Promise.all(promises).then(function(results) {
         assert.deepEqual(results, [1, 1, 1]);
-         element._fetchSharedCacheURL('/foo').then(function(foo) {
+        element._fetchSharedCacheURL('/foo').then(function(foo) {
           assert.equal(foo, 1);
           fetchJSONStub.restore();
           done();
@@ -84,7 +84,7 @@
 
     test('params are properly encoded', function() {
       var fetchStub = sinon.stub(window, 'fetch', function() {
-        return Promise.resolve({ text: function() {
+        return Promise.resolve({text: function() {
           return Promise.resolve(')]}\'\n{}');
         }});
       });
@@ -101,7 +101,7 @@
     test('request callbacks can be canceled', function(done) {
       var cancelCalled = false;
       var fetchStub = sinon.stub(window, 'fetch', function() {
-        return Promise.resolve({ body: {
+        return Promise.resolve({body: {
           cancel: function() { cancelCalled = true; }
         }});
       });
@@ -140,6 +140,7 @@
           assert.deepEqual(obj.comments[0], {
             message: 'this isn’t quite right',
           });
+          fetchJSONStub.restore();
           done();
         });
     });
@@ -190,6 +191,7 @@
           assert.deepEqual(obj.comments[1], {
             message: '¯\\_(ツ)_/¯',
           });
+          fetchJSONStub.restore();
           done();
         });
     });