rebaseline_server: add tabs, and ability to submit new baselines to the server

Tabs allow the user to divide the tests into groups:
hide these for now, approve these, etc.

(SkipBuildbotRuns)

R=borenet@google.com

Review URL: https://codereview.chromium.org/28903008

git-svn-id: http://skia.googlecode.com/svn/trunk@11915 2bbb7eff-a529-9590-31e7-b0007b416f81
diff --git a/gm/rebaseline_server/static/view.html b/gm/rebaseline_server/static/view.html
index 9f0158d..9bb01fc 100644
--- a/gm/rebaseline_server/static/view.html
+++ b/gm/rebaseline_server/static/view.html
@@ -6,6 +6,7 @@
   <title ng-bind="windowTitle"></title>
   <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.1.5/angular.js"></script>
   <script src="loader.js"></script>
+  <link rel="stylesheet" href="view.css">
 </head>
 
 <body>
@@ -13,16 +14,69 @@
     {{loadingMessage}}
   </em>
 
-  <div ng-hide="!categories">
+  <div ng-hide="!categories"><!-- everything: hide until data is loaded -->
+
     <div ng-hide="!(header.isEditable && header.isExported)"
          style="background-color:#ffbb00">
       WARNING!  These results are editable and exported, so any user
       who can connect to this server over the network can modify them.
     </div>
+
+    <div style="background-color:#bbffbb"><!-- TODOs -->
+      <p>
+      TODO(epoger):
+      <input type="checkbox" name="showTodosCheckbox" value="true"
+             ng-checked="showTodos == true"
+             ng-click="showTodos = !showTodos">
+      show
+      <ul ng-hide="!showTodos">
+        <li>
+          If server was run with --reload flag, automatically check for
+          new results and tell the user when new results are available
+          (the user can reload the page if he wants to see them).
+        </li><li>
+          Add ability to filter builder and test names
+          (using a free-form text field, with partial string match)
+        </li><li>
+          Add more columns, such as pixel diffs, notes/bugs,
+          ignoreFailure boolean
+        </li><li>
+          Improve the column sorting, as per
+          <a href="http://jsfiddle.net/vojtajina/js64b/14/">
+            http://jsfiddle.net/vojtajina/js64b/14/
+          </a>
+        </li><li>
+          Right now, if you change which column is used to
+          sort the data, the column widths may fluctuate based on the
+          longest string <i>currently visible</i> within the top {{displayLimit}}
+          results.  Can we fix the column widths to be wide enough to hold
+          any result, even the currently hidden results?
+        </li>
+      </ul>
+    </div><!-- TODOs -->
+
     <div ng-hide="!(header.timeUpdated)">
       Results current as of {{localTimeString(header.timeUpdated)}}
     </div>
-  <table border="1">
+
+    <div style="font-size:20px"><!-- tabs -->
+      <div ng-repeat="tab in tabs"
+           style="display:inline-block">
+        <div class="tab-{{tab == viewingTab}}"
+             style="display:inline-block"
+             ng-click="setViewingTab(tab)">
+          &nbsp;{{tab}} ({{numResultsPerTab[tab]}})&nbsp;
+        </div>
+        <div style="display:inline-block">
+          &nbsp;
+        </div>
+      </div>
+    </div><!-- tabs -->
+
+    <div class="tab-true"><!-- display of current tab -->
+
+    <br>
+    <table ng-hide="viewingTab != defaultTab" border="1">
     <tr>
       <th colspan="2">
         Filters
@@ -80,49 +134,52 @@
     </tr>
   </table>
 
-    <p>
-      TODO(epoger):
-      <input type="checkbox" name="showTodosCheckbox" value="true"
-             ng-checked="showTodos == true"
-             ng-click="showTodos = !showTodos">
-      show
-      <ul ng-hide="!showTodos">
-        <li>
-          Implement editing of results (we have added the --editable
-          flag to the server, but it&#39;s not fully implemented yet).
-          <div ng-hide="!header.isEditable">
-            Currently selected items are: {{selectedItems}}
-          </div>
-        </li><li>
-          If server was run with --reload flag, automatically check for
-          new results and tell the user when new results are available
-          (the user can reload the page if he wants to see them).
-        </li><li>
-          Add ability to filter builder and test names
-          (using a free-form text field, with partial string match)
-        </li><li>
-          Add more columns, such as pixel diffs, notes/bugs,
-          ignoreFailure boolean
-        </li><li>
-          Improve the column sorting, as per
-          <a href="http://jsfiddle.net/vojtajina/js64b/14/">
-            http://jsfiddle.net/vojtajina/js64b/14/
-          </a>
-        </li><li>
-          Right now, if you change which column is used to
-          sort the data, the column widths may fluctuate based on the
-          longest string <i>currently visible</i> within the top {{displayLimit}}
-          results.  Can we fix the column widths to be wide enough to hold
-          any result, even the currently hidden results?
-        </li>
-      </ul>
       <p>
-      Found {{filteredTestData.length}} matches, and displaying the first
-      {{displayLimit}}: <br>
-      <!-- TODO(epoger): If (displayLimit <= filteredTestData.length),
-           modify this message to indicate that all results are shown. -->
-      (click on the column header radio buttons to re-sort by that column)
+
+      <div ng-hide="'Pending Approval' != viewingTab">
+        <div style="display:inline-block">
+          <button style="font-size:20px"
+                  ng-click="submitApprovals(filteredTestData)"
+                  ng-disabled="submitPending || (filteredTestData.length == 0)">
+            Update these {{filteredTestData.length}} expectations on the server
+          </button>
+        </div>
+        <div style="display:inline-block">
+          <div style="font-size:20px"
+               ng-hide="!submitPending">
+            Submitting, please wait...
+          </div>
+        </div>
+      </div>
+
+      <p>
+
+      <div>
+        <div style="float:left">
+          Found {{filteredTestData.length}} matches;
+          <span ng-hide="filteredTestData.length <= limitedTestData.length">
+            displaying the first {{limitedTestData.length}}
+          </span>
+          <span ng-hide="filteredTestData.length > limitedTestData.length">
+            displaying them all
+          </span>
+          <br>
+          (click on the column header radio buttons to re-sort by that column)
+        </div>
+        <div style="float:right">
+          <div ng-repeat="otherTab in tabs">
+            <button ng-click="moveSelectedItemsToTab(otherTab)"
+                    ng-disabled="selectedItems.length == 0"
+                    ng-hide="otherTab == viewingTab">
+              {{selectedItems.length}} move selected tests to {{otherTab}} tab
+            </button>
+          </div>
+        </div>
+        <div style="clear:both">
+        </div>
+      </div>
       <br>
+
       <table border="1">
         <tr>
           <th ng-repeat="categoryName in ['resultType', 'builder', 'test', 'config']">
@@ -149,7 +206,7 @@
                    ng-click="sortResultsBy('actualHashDigest')">
             actual image
           </th>
-          <th ng-hide="!header.isEditable">
+          <th>
             <!-- item-selection checkbox column -->
           </th>
         </tr>
@@ -168,7 +225,7 @@
               <img width="{{imageSize}}" src="http://chromium-skia-gm.commondatastorage.googleapis.com/gm/{{result.actualHashType}}/{{result.test}}/{{result.actualHashDigest}}.png"/>
             </a>
           </td>
-          <td ng-hide="!header.isEditable">
+          <td>
             <input type="checkbox"
                    name="rowSelect"
                    value="{{result.index}}"
@@ -176,7 +233,8 @@
                    ng-click="toggleItemSelected(result.index)">
         </tr>
       </table>
-  </div>
+  </div><!-- display of current tab -->
+  </div><!-- everything: hide until data is loaded -->
 
   <!-- TODO(epoger): Can we get the base URLs (commondatastorage and
        issues list) from