Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(2100)

Side by Side Diff: gm/rebaseline_server/static/loader.js

Issue 28903008: rebaseline_server: add tabs, and ability to submit new baselines to the server (Closed) Base URL: http://skia.googlecode.com/svn/trunk/
Patch Set: more Created 7 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « gm/rebaseline_server/server.py ('k') | gm/rebaseline_server/static/view.css » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 /* 1 /*
2 * Loader: 2 * Loader:
3 * Reads GM result reports written out by results.py, and imports 3 * Reads GM result reports written out by results.py, and imports
4 * them into $scope.categories and $scope.testData . 4 * them into $scope.categories and $scope.testData .
5 */ 5 */
6 var Loader = angular.module( 6 var Loader = angular.module(
7 'Loader', 7 'Loader',
8 [] 8 []
9 ); 9 );
10 10
11 // TODO(epoger): Combine ALL of our filtering operations (including 11 // TODO(epoger): Combine ALL of our filtering operations (including
12 // truncation) into this one filter, so that runs most efficiently? 12 // truncation) into this one filter, so that runs most efficiently?
13 // (We would have to make sure truncation still took place after 13 // (We would have to make sure truncation still took place after
14 // sorting, though.) 14 // sorting, though.)
15 Loader.filter( 15 Loader.filter(
16 'removeHiddenItems', 16 'removeHiddenItems',
17 function() { 17 function() {
18 return function(unfilteredItems, hiddenResultTypes, hiddenConfigs) { 18 return function(unfilteredItems, hiddenResultTypes, hiddenConfigs,
19 viewingTab) {
19 var filteredItems = []; 20 var filteredItems = [];
20 for (var i = 0; i < unfilteredItems.length; i++) { 21 for (var i = 0; i < unfilteredItems.length; i++) {
21 var item = unfilteredItems[i]; 22 var item = unfilteredItems[i];
22 if (!(true == hiddenResultTypes[item.resultType]) && 23 if (!(true == hiddenResultTypes[item.resultType]) &&
23 !(true == hiddenConfigs[item.config])) { 24 !(true == hiddenConfigs[item.config]) &&
25 (viewingTab == item.tab)) {
24 filteredItems.push(item); 26 filteredItems.push(item);
25 } 27 }
26 } 28 }
27 return filteredItems; 29 return filteredItems;
28 }; 30 };
29 } 31 }
30 ); 32 );
31 33
32 Loader.controller( 34 Loader.controller(
33 'Loader.Controller', 35 'Loader.Controller',
34 function($scope, $http, $filter, $location) { 36 function($scope, $http, $filter, $location) {
35 $scope.windowTitle = "Loading GM Results..."; 37 $scope.windowTitle = "Loading GM Results...";
36 var resultsToLoad = $location.search().resultsToLoad; 38 var resultsToLoad = $location.search().resultsToLoad;
37 $scope.loadingMessage = "Loading results of type '" + resultsToLoad + 39 $scope.loadingMessage = "Loading results of type '" + resultsToLoad +
38 "', please wait..."; 40 "', please wait...";
39 41
40 $http.get("/results/" + resultsToLoad).success( 42 $http.get("/results/" + resultsToLoad).success(
41 function(data, status, header, config) { 43 function(data, status, header, config) {
42 $scope.loadingMessage = "Processing data, please wait..."; 44 $scope.loadingMessage = "Processing data, please wait...";
43 45
44 $scope.header = data.header; 46 $scope.header = data.header;
45 $scope.categories = data.categories; 47 $scope.categories = data.categories;
46 $scope.testData = data.testData; 48 $scope.testData = data.testData;
47 $scope.sortColumn = 'test'; 49 $scope.sortColumn = 'test';
48 $scope.showTodos = true; 50 $scope.showTodos = false;
49 51
52 // Create the list of tabs (lists into which the user can file each
53 // test). This may vary, depending on isEditable.
54 $scope.tabs = [
55 'Unfiled', 'Hidden'
56 ];
57 if (data.header.isEditable) {
58 $scope.tabs = $scope.tabs.concat(
59 ['Pending Approval']);
60 }
61 $scope.defaultTab = $scope.tabs[0];
62 $scope.viewingTab = $scope.defaultTab;
63
64 // Track the number of results on each tab.
65 $scope.numResultsPerTab = {};
66 for (var i = 0; i < $scope.tabs.length; i++) {
67 $scope.numResultsPerTab[$scope.tabs[i]] = 0;
68 }
69 $scope.numResultsPerTab[$scope.defaultTab] = $scope.testData.length;
70
71 // Add index and tab fields to all records.
50 for (var i = 0; i < $scope.testData.length; i++) { 72 for (var i = 0; i < $scope.testData.length; i++) {
51 $scope.testData[i].index = i; 73 $scope.testData[i].index = i;
74 $scope.testData[i].tab = $scope.defaultTab;
52 } 75 }
53 76
54 $scope.hiddenResultTypes = { 77 $scope.hiddenResultTypes = {
55 'failure-ignored': true, 78 'failure-ignored': true,
56 'no-comparison': true, 79 'no-comparison': true,
57 'succeeded': true, 80 'succeeded': true,
58 }; 81 };
59 $scope.hiddenConfigs = {}; 82 $scope.hiddenConfigs = {};
60 $scope.selectedItems = {}; 83 $scope.selectedItems = [];
61 84
62 $scope.updateResults(); 85 $scope.updateResults();
63 $scope.loadingMessage = ""; 86 $scope.loadingMessage = "";
64 $scope.windowTitle = "Current GM Results"; 87 $scope.windowTitle = "Current GM Results";
65 } 88 }
66 ).error( 89 ).error(
67 function(data, status, header, config) { 90 function(data, status, header, config) {
68 $scope.loadingMessage = "Failed to load results of type '" 91 $scope.loadingMessage = "Failed to load results of type '"
69 + resultsToLoad + "'"; 92 + resultsToLoad + "'";
70 $scope.windowTitle = "Failed to Load GM Results"; 93 $scope.windowTitle = "Failed to Load GM Results";
71 } 94 }
72 ); 95 );
73 96
74 $scope.isItemSelected = function(index) { 97 $scope.isItemSelected = function(index) {
75 return (true == $scope.selectedItems[index]); 98 return (-1 != $scope.selectedItems.indexOf(index));
76 } 99 }
77 $scope.toggleItemSelected = function(index) { 100 $scope.toggleItemSelected = function(index) {
78 if (true == $scope.selectedItems[index]) { 101 var i = $scope.selectedItems.indexOf(index);
79 delete $scope.selectedItems[index]; 102 if (-1 == i) {
103 $scope.selectedItems.push(index);
80 } else { 104 } else {
81 $scope.selectedItems[index] = true; 105 $scope.selectedItems.splice(i, 1);
82 } 106 }
83 // unlike other toggle methods below, does not set 107 // unlike other toggle methods below, does not set
84 // $scope.areUpdatesPending = true; 108 // $scope.areUpdatesPending = true;
85 } 109 }
86 110
87 $scope.isHiddenResultType = function(thisResultType) { 111 $scope.isHiddenResultType = function(thisResultType) {
88 return (true == $scope.hiddenResultTypes[thisResultType]); 112 return (true == $scope.hiddenResultTypes[thisResultType]);
89 } 113 }
90 $scope.toggleHiddenResultType = function(thisResultType) { 114 $scope.toggleHiddenResultType = function(thisResultType) {
91 if (true == $scope.hiddenResultTypes[thisResultType]) { 115 if (true == $scope.hiddenResultTypes[thisResultType]) {
(...skipping 14 matching lines...) Expand all
106 } 130 }
107 $scope.toggleHiddenConfig = function(thisConfig) { 131 $scope.toggleHiddenConfig = function(thisConfig) {
108 if (true == $scope.hiddenConfigs[thisConfig]) { 132 if (true == $scope.hiddenConfigs[thisConfig]) {
109 delete $scope.hiddenConfigs[thisConfig]; 133 delete $scope.hiddenConfigs[thisConfig];
110 } else { 134 } else {
111 $scope.hiddenConfigs[thisConfig] = true; 135 $scope.hiddenConfigs[thisConfig] = true;
112 } 136 }
113 $scope.areUpdatesPending = true; 137 $scope.areUpdatesPending = true;
114 } 138 }
115 139
140 $scope.setViewingTab = function(tab) {
141 $scope.viewingTab = tab;
142 $scope.updateResults();
143 }
144
116 $scope.localTimeString = function(secondsPastEpoch) { 145 $scope.localTimeString = function(secondsPastEpoch) {
117 var d = new Date(secondsPastEpoch * 1000); 146 var d = new Date(secondsPastEpoch * 1000);
118 return d.toString(); 147 return d.toString();
119 } 148 }
120 149
150 /**
151 * Move the items in $scope.selectedItems to a different tab,
152 * and then clear $scope.selectedItems.
153 *
154 * @param newTab (string): name of the tab to move the tests to
155 */
156 $scope.moveSelectedItemsToTab = function(newTab) {
157 $scope.moveItemsToTab($scope.selectedItems, newTab);
158 $scope.selectedItems = [];
159 $scope.updateResults();
160 }
161
162 /**
163 * Move a subset of $scope.testData to a different tab.
164 *
165 * @param itemIndices (array of ints): indices into $scope.testData
166 * indicating which test results to move
167 * @param newTab (string): name of the tab to move the tests to
168 */
169 $scope.moveItemsToTab = function(itemIndices, newTab) {
170 var itemIndex;
171 var numItems = itemIndices.length;
172 for (var i = 0; i < numItems; i++) {
173 itemIndex = itemIndices[i];
174 $scope.numResultsPerTab[$scope.testData[itemIndex].tab]--;
175 $scope.testData[itemIndex].tab = newTab;
176 }
177 $scope.numResultsPerTab[newTab] += numItems;
178 }
179
121 $scope.updateResults = function() { 180 $scope.updateResults = function() {
122 $scope.displayLimit = $scope.displayLimitPending; 181 $scope.displayLimit = $scope.displayLimitPending;
123 // TODO(epoger): Every time we apply a filter, AngularJS creates 182 // TODO(epoger): Every time we apply a filter, AngularJS creates
124 // another copy of the array. Is there a way we can filter out 183 // another copy of the array. Is there a way we can filter out
125 // the items as they are displayed, rather than storing multiple 184 // the items as they are displayed, rather than storing multiple
126 // array copies? (For better performance.) 185 // array copies? (For better performance.)
127 $scope.filteredTestData = 186
128 $filter("orderBy")( 187 if ($scope.viewingTab == $scope.defaultTab) {
129 $filter("removeHiddenItems")( 188 $scope.filteredTestData =
130 $scope.testData, 189 $filter("orderBy")(
131 $scope.hiddenResultTypes, 190 $filter("removeHiddenItems")(
132 $scope.hiddenConfigs 191 $scope.testData,
133 ), 192 $scope.hiddenResultTypes,
134 $scope.sortColumn); 193 $scope.hiddenConfigs,
135 $scope.limitedTestData = $filter("limitTo")( 194 $scope.viewingTab
136 $scope.filteredTestData, $scope.displayLimit); 195 ),
196 $scope.sortColumn);
197 $scope.limitedTestData = $filter("limitTo")(
198 $scope.filteredTestData, $scope.displayLimit);
199 } else {
200 $scope.filteredTestData =
201 $filter("orderBy")(
202 $filter("filter")(
203 $scope.testData,
204 {tab: $scope.viewingTab},
205 true
206 ),
207 $scope.sortColumn);
208 $scope.limitedTestData = $filter("limitTo")(
209 $scope.filteredTestData, $scope.displayLimit);
210 }
137 $scope.imageSize = $scope.imageSizePending; 211 $scope.imageSize = $scope.imageSizePending;
138 $scope.areUpdatesPending = false; 212 $scope.areUpdatesPending = false;
139 } 213 }
140 214
141 $scope.sortResultsBy = function(sortColumn) { 215 $scope.sortResultsBy = function(sortColumn) {
142 $scope.sortColumn = sortColumn; 216 $scope.sortColumn = sortColumn;
143 $scope.updateResults(); 217 $scope.updateResults();
144 } 218 }
219
220 /**
221 * Tell the server that the actual results of these particular tests
222 * are acceptable.
223 *
224 * @param testDataSubset an array of test results, most likely a subset of
225 * $scope.testData (perhaps with some modifications)
226 */
227 $scope.submitApprovals = function(testDataSubset) {
228 $scope.submitPending = true;
229 var newResults = [];
230 for (var i = 0; i < testDataSubset.length; i++) {
231 var actualResult = testDataSubset[i];
232 var expectedResult = {
233 builder: actualResult['builder'],
234 test: actualResult['test'],
235 config: actualResult['config'],
236 expectedHashType: actualResult['actualHashType'],
237 expectedHashDigest: actualResult['actualHashDigest'],
238 };
239 newResults.push(expectedResult);
240 }
241 $http({
242 method: "POST",
243 url: "/edits",
244 data: {
245 oldResultsType: $scope.header.type,
246 oldResultsHash: $scope.header.dataHash,
247 modifications: newResults
248 }
249 }).success(function(data, status, headers, config) {
250 var itemIndicesToMove = [];
251 for (var i = 0; i < testDataSubset.length; i++) {
252 itemIndicesToMove.push(testDataSubset[i].index);
253 }
254 $scope.moveItemsToTab(itemIndicesToMove,
255 "HackToMakeSureThisItemDisappears");
256 $scope.updateResults();
257 alert("New baselines submitted successfully!\n\n" +
258 "You still need to commit the updated expectations files on " +
259 "the server side to the Skia repo.\n\n" +
260 "Also: in order to see the complete updated data, or to submit " +
261 "more baselines, you will need to reload your client.");
262 $scope.submitPending = false;
263 }).error(function(data, status, headers, config) {
264 alert("There was an error submitting your baselines.\n\n" +
265 "Please see server-side log for details.");
266 $scope.submitPending = false;
267 });
268 }
145 } 269 }
146 ); 270 );
OLDNEW
« no previous file with comments | « gm/rebaseline_server/server.py ('k') | gm/rebaseline_server/static/view.css » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698