Settings title and unsaved changes warnings

Properly sets the document title when the PolyGerrit Settings screen is
shown, and adds markers to settings headers when they contain unsaved
settings changes.

Bug: Issue 3911
Change-Id: Ia6977014047d540be3ddbfe4e8d3856753cd21b3
diff --git a/polygerrit-ui/app/elements/settings/gr-settings-view/gr-settings-view.html b/polygerrit-ui/app/elements/settings/gr-settings-view/gr-settings-view.html
index 6b7435d..08fee30 100644
--- a/polygerrit-ui/app/elements/settings/gr-settings-view/gr-settings-view.html
+++ b/polygerrit-ui/app/elements/settings/gr-settings-view/gr-settings-view.html
@@ -36,6 +36,10 @@
       h1 {
         margin-bottom: .1em;
       }
+      h2.edited:after {
+        color: #444;
+        content: ' *';
+      }
       fieldset {
         border: none;
         margin: 0 0 2em 2em;
@@ -104,7 +108,7 @@
             </span>
           </section>
         </fieldset>
-        <h2>Preferences</h2>
+        <h2 class$="[[_computeHeaderClass(_prefsChanged)]]">Preferences</h2>
         <fieldset id="preferences">
           <section>
             <span class="title">Changes Per Page</span>
@@ -168,7 +172,7 @@
               on-tap="_handleSavePreferences"
               disabled="[[!_prefsChanged]]">Save Changes</gr-button>
         </fieldset>
-        <h2>Menu</h2>
+        <h2 class$="[[_computeHeaderClass(_menuChanged)]]">Menu</h2>
         <fieldset id="menu">
           <gr-menu-editor menu-items="{{_localMenu}}"></gr-menu-editor>
           <gr-button
@@ -176,7 +180,9 @@
               on-tap="_handleSaveMenu"
               disabled="[[!_menuChanged]]">Save Changes</gr-button>
         </fieldset>
-        <h2>Notifications</h2>
+        <h2 class$="[[_computeHeaderClass(_watchedProjectsChanged)]]">
+          Notifications
+        </h2>
         <fieldset id="watchedProjects">
           <gr-watched-projects-editor
               on-project-removed="_handleWatchedProjectRemoved"
diff --git a/polygerrit-ui/app/elements/settings/gr-settings-view/gr-settings-view.js b/polygerrit-ui/app/elements/settings/gr-settings-view/gr-settings-view.js
index c888365..255565e 100644
--- a/polygerrit-ui/app/elements/settings/gr-settings-view/gr-settings-view.js
+++ b/polygerrit-ui/app/elements/settings/gr-settings-view/gr-settings-view.js
@@ -25,6 +25,12 @@
   Polymer({
     is: 'gr-settings-view',
 
+    /**
+     * Fired when the title of the page should change.
+     *
+     * @event title-change
+     */
+
     properties: {
       account: {
         type: Object,
@@ -72,6 +78,8 @@
     ],
 
     attached: function() {
+      this.fire('title-change', {title: 'Settings'});
+
       var promises = [];
 
       promises.push(this.$.restAPI.getAccount().then(function(account) {
@@ -169,5 +177,9 @@
           this._watchedProjectsToRemove = [];
         }.bind(this));
     },
+
+    _computeHeaderClass: function(changed) {
+      return changed ? 'edited' : '';
+    },
   });
 })();
diff --git a/polygerrit-ui/app/elements/settings/gr-settings-view/gr-settings-view_test.html b/polygerrit-ui/app/elements/settings/gr-settings-view/gr-settings-view_test.html
index d06a915..f0c5369 100644
--- a/polygerrit-ui/app/elements/settings/gr-settings-view/gr-settings-view_test.html
+++ b/polygerrit-ui/app/elements/settings/gr-settings-view/gr-settings-view_test.html
@@ -30,6 +30,12 @@
   </template>
 </test-fixture>
 
+<test-fixture id="blank">
+  <template>
+    <div></div>
+  </template>
+</test-fixture>
+
 <script>
   suite('gr-settings-view tests', function() {
     var element;
@@ -104,6 +110,22 @@
           'Sat, 01 Jan 2000 00:00:00 GMT');
     });
 
+    test('calls the title-change event', function() {
+      var titleChangedStub = sinon.stub();
+
+      // Create a new view.
+      var newElement = document.createElement('gr-settings-view');
+      newElement.addEventListener('title-change', titleChangedStub);
+
+      // Attach it to the fixture.
+      var blank = fixture('blank');
+      blank.appendChild(newElement);
+
+      assert.isTrue(titleChangedStub.called);
+      assert.equal(titleChangedStub.getCall(0).args[0].detail.title,
+          'Settings');
+    });
+
     test('user preferences', function(done) {
       // Rendered with the expected preferences selected.
       assert.equal(valueOf('Changes Per Page', 'preferences')