aboutsummaryrefslogtreecommitdiffhomepage
path: root/gm/rebaseline_server/static
diff options
context:
space:
mode:
authorGravatar epoger@google.com <epoger@google.com@2bbb7eff-a529-9590-31e7-b0007b416f81>2013-10-23 15:07:26 +0000
committerGravatar epoger@google.com <epoger@google.com@2bbb7eff-a529-9590-31e7-b0007b416f81>2013-10-23 15:07:26 +0000
commiteb832599b631a09b180ea3615347adba6bd5e363 (patch)
treee4cba2c9055d0da638db1d1a2751c39fb783e832 /gm/rebaseline_server/static
parent1f81fd6546c111e21bc665657e976b9d842192df (diff)
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
Diffstat (limited to 'gm/rebaseline_server/static')
-rw-r--r--gm/rebaseline_server/static/loader.js160
-rw-r--r--gm/rebaseline_server/static/view.css6
-rw-r--r--gm/rebaseline_server/static/view.html148
3 files changed, 251 insertions, 63 deletions
diff --git a/gm/rebaseline_server/static/loader.js b/gm/rebaseline_server/static/loader.js
index 80f84c6a3a..09b66d5546 100644
--- a/gm/rebaseline_server/static/loader.js
+++ b/gm/rebaseline_server/static/loader.js
@@ -15,12 +15,14 @@ var Loader = angular.module(
Loader.filter(
'removeHiddenItems',
function() {
- return function(unfilteredItems, hiddenResultTypes, hiddenConfigs) {
+ return function(unfilteredItems, hiddenResultTypes, hiddenConfigs,
+ viewingTab) {
var filteredItems = [];
for (var i = 0; i < unfilteredItems.length; i++) {
var item = unfilteredItems[i];
if (!(true == hiddenResultTypes[item.resultType]) &&
- !(true == hiddenConfigs[item.config])) {
+ !(true == hiddenConfigs[item.config]) &&
+ (viewingTab == item.tab)) {
filteredItems.push(item);
}
}
@@ -45,10 +47,31 @@ Loader.controller(
$scope.categories = data.categories;
$scope.testData = data.testData;
$scope.sortColumn = 'test';
- $scope.showTodos = true;
+ $scope.showTodos = false;
+ // Create the list of tabs (lists into which the user can file each
+ // test). This may vary, depending on isEditable.
+ $scope.tabs = [
+ 'Unfiled', 'Hidden'
+ ];
+ if (data.header.isEditable) {
+ $scope.tabs = $scope.tabs.concat(
+ ['Pending Approval']);
+ }
+ $scope.defaultTab = $scope.tabs[0];
+ $scope.viewingTab = $scope.defaultTab;
+
+ // Track the number of results on each tab.
+ $scope.numResultsPerTab = {};
+ for (var i = 0; i < $scope.tabs.length; i++) {
+ $scope.numResultsPerTab[$scope.tabs[i]] = 0;
+ }
+ $scope.numResultsPerTab[$scope.defaultTab] = $scope.testData.length;
+
+ // Add index and tab fields to all records.
for (var i = 0; i < $scope.testData.length; i++) {
$scope.testData[i].index = i;
+ $scope.testData[i].tab = $scope.defaultTab;
}
$scope.hiddenResultTypes = {
@@ -57,7 +80,7 @@ Loader.controller(
'succeeded': true,
};
$scope.hiddenConfigs = {};
- $scope.selectedItems = {};
+ $scope.selectedItems = [];
$scope.updateResults();
$scope.loadingMessage = "";
@@ -72,13 +95,14 @@ Loader.controller(
);
$scope.isItemSelected = function(index) {
- return (true == $scope.selectedItems[index]);
+ return (-1 != $scope.selectedItems.indexOf(index));
}
$scope.toggleItemSelected = function(index) {
- if (true == $scope.selectedItems[index]) {
- delete $scope.selectedItems[index];
+ var i = $scope.selectedItems.indexOf(index);
+ if (-1 == i) {
+ $scope.selectedItems.push(index);
} else {
- $scope.selectedItems[index] = true;
+ $scope.selectedItems.splice(i, 1);
}
// unlike other toggle methods below, does not set
// $scope.areUpdatesPending = true;
@@ -113,27 +137,77 @@ Loader.controller(
$scope.areUpdatesPending = true;
}
+ $scope.setViewingTab = function(tab) {
+ $scope.viewingTab = tab;
+ $scope.updateResults();
+ }
+
$scope.localTimeString = function(secondsPastEpoch) {
var d = new Date(secondsPastEpoch * 1000);
return d.toString();
}
+ /**
+ * Move the items in $scope.selectedItems to a different tab,
+ * and then clear $scope.selectedItems.
+ *
+ * @param newTab (string): name of the tab to move the tests to
+ */
+ $scope.moveSelectedItemsToTab = function(newTab) {
+ $scope.moveItemsToTab($scope.selectedItems, newTab);
+ $scope.selectedItems = [];
+ $scope.updateResults();
+ }
+
+ /**
+ * Move a subset of $scope.testData to a different tab.
+ *
+ * @param itemIndices (array of ints): indices into $scope.testData
+ * indicating which test results to move
+ * @param newTab (string): name of the tab to move the tests to
+ */
+ $scope.moveItemsToTab = function(itemIndices, newTab) {
+ var itemIndex;
+ var numItems = itemIndices.length;
+ for (var i = 0; i < numItems; i++) {
+ itemIndex = itemIndices[i];
+ $scope.numResultsPerTab[$scope.testData[itemIndex].tab]--;
+ $scope.testData[itemIndex].tab = newTab;
+ }
+ $scope.numResultsPerTab[newTab] += numItems;
+ }
+
$scope.updateResults = function() {
$scope.displayLimit = $scope.displayLimitPending;
// TODO(epoger): Every time we apply a filter, AngularJS creates
// another copy of the array. Is there a way we can filter out
// the items as they are displayed, rather than storing multiple
// array copies? (For better performance.)
- $scope.filteredTestData =
- $filter("orderBy")(
- $filter("removeHiddenItems")(
- $scope.testData,
- $scope.hiddenResultTypes,
- $scope.hiddenConfigs
- ),
- $scope.sortColumn);
- $scope.limitedTestData = $filter("limitTo")(
- $scope.filteredTestData, $scope.displayLimit);
+
+ if ($scope.viewingTab == $scope.defaultTab) {
+ $scope.filteredTestData =
+ $filter("orderBy")(
+ $filter("removeHiddenItems")(
+ $scope.testData,
+ $scope.hiddenResultTypes,
+ $scope.hiddenConfigs,
+ $scope.viewingTab
+ ),
+ $scope.sortColumn);
+ $scope.limitedTestData = $filter("limitTo")(
+ $scope.filteredTestData, $scope.displayLimit);
+ } else {
+ $scope.filteredTestData =
+ $filter("orderBy")(
+ $filter("filter")(
+ $scope.testData,
+ {tab: $scope.viewingTab},
+ true
+ ),
+ $scope.sortColumn);
+ $scope.limitedTestData = $filter("limitTo")(
+ $scope.filteredTestData, $scope.displayLimit);
+ }
$scope.imageSize = $scope.imageSizePending;
$scope.areUpdatesPending = false;
}
@@ -142,5 +216,55 @@ Loader.controller(
$scope.sortColumn = sortColumn;
$scope.updateResults();
}
+
+ /**
+ * Tell the server that the actual results of these particular tests
+ * are acceptable.
+ *
+ * @param testDataSubset an array of test results, most likely a subset of
+ * $scope.testData (perhaps with some modifications)
+ */
+ $scope.submitApprovals = function(testDataSubset) {
+ $scope.submitPending = true;
+ var newResults = [];
+ for (var i = 0; i < testDataSubset.length; i++) {
+ var actualResult = testDataSubset[i];
+ var expectedResult = {
+ builder: actualResult['builder'],
+ test: actualResult['test'],
+ config: actualResult['config'],
+ expectedHashType: actualResult['actualHashType'],
+ expectedHashDigest: actualResult['actualHashDigest'],
+ };
+ newResults.push(expectedResult);
+ }
+ $http({
+ method: "POST",
+ url: "/edits",
+ data: {
+ oldResultsType: $scope.header.type,
+ oldResultsHash: $scope.header.dataHash,
+ modifications: newResults
+ }
+ }).success(function(data, status, headers, config) {
+ var itemIndicesToMove = [];
+ for (var i = 0; i < testDataSubset.length; i++) {
+ itemIndicesToMove.push(testDataSubset[i].index);
+ }
+ $scope.moveItemsToTab(itemIndicesToMove,
+ "HackToMakeSureThisItemDisappears");
+ $scope.updateResults();
+ alert("New baselines submitted successfully!\n\n" +
+ "You still need to commit the updated expectations files on " +
+ "the server side to the Skia repo.\n\n" +
+ "Also: in order to see the complete updated data, or to submit " +
+ "more baselines, you will need to reload your client.");
+ $scope.submitPending = false;
+ }).error(function(data, status, headers, config) {
+ alert("There was an error submitting your baselines.\n\n" +
+ "Please see server-side log for details.");
+ $scope.submitPending = false;
+ });
+ }
}
);
diff --git a/gm/rebaseline_server/static/view.css b/gm/rebaseline_server/static/view.css
new file mode 100644
index 0000000000..e4eeb0f5a3
--- /dev/null
+++ b/gm/rebaseline_server/static/view.css
@@ -0,0 +1,6 @@
+.tab-true {
+ background-color: #ccccff;
+}
+.tab-false {
+ background-color: #8888ff;
+}
diff --git a/gm/rebaseline_server/static/view.html b/gm/rebaseline_server/static/view.html
index 9f0158d579..9bb01fc0c5 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}}
+ <p>
+
+ <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>
- </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>
+ </div>
+ </div>
+
<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>
+ <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