OLD | NEW |
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 |
(...skipping 24 matching lines...) Expand all Loading... |
35 return filteredItems; | 35 return filteredItems; |
36 }; | 36 }; |
37 } | 37 } |
38 ); | 38 ); |
39 | 39 |
40 | 40 |
41 Loader.controller( | 41 Loader.controller( |
42 'Loader.Controller', | 42 'Loader.Controller', |
43 function($scope, $http, $filter, $location, $timeout) { | 43 function($scope, $http, $filter, $location, $timeout) { |
44 $scope.windowTitle = "Loading GM Results..."; | 44 $scope.windowTitle = "Loading GM Results..."; |
45 var resultsToLoad = $location.search().resultsToLoad; | 45 $scope.resultsToLoad = $location.search().resultsToLoad; |
46 $scope.loadingMessage = "Loading results of type '" + resultsToLoad + | 46 $scope.loadingMessage = "Loading results of type '" + $scope.resultsToLoad + |
47 "', please wait..."; | 47 "', please wait..."; |
48 | 48 |
49 /** | 49 /** |
50 * On initial page load, load a full dictionary of results. | 50 * On initial page load, load a full dictionary of results. |
51 * Once the dictionary is loaded, unhide the page elements so they can | 51 * Once the dictionary is loaded, unhide the page elements so they can |
52 * render the data. | 52 * render the data. |
53 */ | 53 */ |
54 $http.get("/results/" + resultsToLoad).success( | 54 $http.get("/results/" + $scope.resultsToLoad).success( |
55 function(data, status, header, config) { | 55 function(data, status, header, config) { |
56 if (data.header.resultsStillLoading) { | 56 if (data.header.resultsStillLoading) { |
57 $scope.loadingMessage = | 57 $scope.loadingMessage = |
58 "Server is still loading initial results; will retry at " + | 58 "Server is still loading initial results; will retry at " + |
59 $scope.localTimeString(data.header.timeNextUpdateAvailable); | 59 $scope.localTimeString(data.header.timeNextUpdateAvailable); |
60 $timeout( | 60 $timeout( |
61 function(){location.reload();}, | 61 function(){location.reload();}, |
62 (data.header.timeNextUpdateAvailable * 1000) - new Date().getTime(
)); | 62 (data.header.timeNextUpdateAvailable * 1000) - new Date().getTime(
)); |
63 } else { | 63 } else { |
64 $scope.loadingMessage = "Processing data, please wait..."; | 64 $scope.loadingMessage = "Processing data, please wait..."; |
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
111 }; | 111 }; |
112 $scope.allResultTypes = Object.keys(data.categories['resultType']); | 112 $scope.allResultTypes = Object.keys(data.categories['resultType']); |
113 $scope.hiddenConfigs = {}; | 113 $scope.hiddenConfigs = {}; |
114 $scope.allConfigs = Object.keys(data.categories['config']); | 114 $scope.allConfigs = Object.keys(data.categories['config']); |
115 | 115 |
116 // Associative array of partial string matches per category. | 116 // Associative array of partial string matches per category. |
117 $scope.categoryValueMatch = {}; | 117 $scope.categoryValueMatch = {}; |
118 $scope.categoryValueMatch.builder = ""; | 118 $scope.categoryValueMatch.builder = ""; |
119 $scope.categoryValueMatch.test = ""; | 119 $scope.categoryValueMatch.test = ""; |
120 | 120 |
| 121 // If any defaults were overridden in the URL, get them now. |
| 122 $scope.queryParameters.load(); |
| 123 |
121 $scope.updateResults(); | 124 $scope.updateResults(); |
122 $scope.loadingMessage = ""; | 125 $scope.loadingMessage = ""; |
123 $scope.windowTitle = "Current GM Results"; | 126 $scope.windowTitle = "Current GM Results"; |
124 } | 127 } |
125 } | 128 } |
126 ).error( | 129 ).error( |
127 function(data, status, header, config) { | 130 function(data, status, header, config) { |
128 $scope.loadingMessage = "Failed to load results of type '" | 131 $scope.loadingMessage = "Failed to load results of type '" |
129 + resultsToLoad + "'"; | 132 + $scope.resultsToLoad + "'"; |
130 $scope.windowTitle = "Failed to Load GM Results"; | 133 $scope.windowTitle = "Failed to Load GM Results"; |
131 } | 134 } |
132 ); | 135 ); |
133 | 136 |
134 | 137 |
135 // | 138 // |
136 // Select/Clear/Toggle all tests. | 139 // Select/Clear/Toggle all tests. |
137 // | 140 // |
138 | 141 |
139 /** | 142 /** |
(...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
213 for (var i = 0; i < numItems; i++) { | 216 for (var i = 0; i < numItems; i++) { |
214 itemIndex = itemIndices[i]; | 217 itemIndex = itemIndices[i]; |
215 $scope.numResultsPerTab[$scope.testData[itemIndex].tab]--; | 218 $scope.numResultsPerTab[$scope.testData[itemIndex].tab]--; |
216 $scope.testData[itemIndex].tab = newTab; | 219 $scope.testData[itemIndex].tab = newTab; |
217 } | 220 } |
218 $scope.numResultsPerTab[newTab] += numItems; | 221 $scope.numResultsPerTab[newTab] += numItems; |
219 } | 222 } |
220 | 223 |
221 | 224 |
222 // | 225 // |
| 226 // $scope.queryParameters: |
| 227 // Transfer parameter values between $scope and the URL query string. |
| 228 // |
| 229 $scope.queryParameters = {}; |
| 230 |
| 231 // load and save functions for parameters of each type |
| 232 // (load a parameter value into $scope from nameValuePairs, |
| 233 // save a parameter value from $scope into nameValuePairs) |
| 234 $scope.queryParameters.copiers = { |
| 235 'simple': { |
| 236 'load': function(nameValuePairs, name) { |
| 237 var value = nameValuePairs[name]; |
| 238 if (value) { |
| 239 $scope[name] = value; |
| 240 } |
| 241 }, |
| 242 'save': function(nameValuePairs, name) { |
| 243 nameValuePairs[name] = $scope[name]; |
| 244 } |
| 245 }, |
| 246 |
| 247 'categoryValueMatch': { |
| 248 'load': function(nameValuePairs, name) { |
| 249 var value = nameValuePairs[name]; |
| 250 if (value) { |
| 251 $scope.categoryValueMatch[name] = value; |
| 252 } |
| 253 }, |
| 254 'save': function(nameValuePairs, name) { |
| 255 nameValuePairs[name] = $scope.categoryValueMatch[name]; |
| 256 } |
| 257 }, |
| 258 |
| 259 'set': { |
| 260 'load': function(nameValuePairs, name) { |
| 261 var value = nameValuePairs[name]; |
| 262 if (value) { |
| 263 var valueArray = value.split(','); |
| 264 $scope[name] = {}; |
| 265 $scope.toggleValuesInSet(valueArray, $scope[name]); |
| 266 } |
| 267 }, |
| 268 'save': function(nameValuePairs, name) { |
| 269 nameValuePairs[name] = Object.keys($scope[name]).join(','); |
| 270 } |
| 271 }, |
| 272 |
| 273 }; |
| 274 |
| 275 // parameter name -> copier objects to load/save parameter value |
| 276 $scope.queryParameters.map = { |
| 277 'resultsToLoad': $scope.queryParameters.copiers.simple, |
| 278 'displayLimitPending': $scope.queryParameters.copiers.simple, |
| 279 'imageSizePending': $scope.queryParameters.copiers.simple, |
| 280 'sortColumn': $scope.queryParameters.copiers.simple, |
| 281 |
| 282 'builder': $scope.queryParameters.copiers.categoryValueMatch, |
| 283 'test': $scope.queryParameters.copiers.categoryValueMatch, |
| 284 |
| 285 'hiddenResultTypes': $scope.queryParameters.copiers.set, |
| 286 'hiddenConfigs': $scope.queryParameters.copiers.set, |
| 287 }; |
| 288 |
| 289 // Loads all parameters into $scope from the URL query string; |
| 290 // any which are not found within the URL will keep their current value. |
| 291 $scope.queryParameters.load = function() { |
| 292 var nameValuePairs = $location.search(); |
| 293 angular.forEach($scope.queryParameters.map, |
| 294 function(copier, paramName) { |
| 295 copier.load(nameValuePairs, paramName); |
| 296 } |
| 297 ); |
| 298 }; |
| 299 |
| 300 // Saves all parameters from $scope into the URL query string. |
| 301 $scope.queryParameters.save = function() { |
| 302 var nameValuePairs = {}; |
| 303 angular.forEach($scope.queryParameters.map, |
| 304 function(copier, paramName) { |
| 305 copier.save(nameValuePairs, paramName); |
| 306 } |
| 307 ); |
| 308 $location.search(nameValuePairs); |
| 309 }; |
| 310 |
| 311 |
| 312 // |
223 // updateResults() and friends. | 313 // updateResults() and friends. |
224 // | 314 // |
225 | 315 |
226 /** | 316 /** |
227 * Set $scope.areUpdatesPending (to enable/disable the Update Results | 317 * Set $scope.areUpdatesPending (to enable/disable the Update Results |
228 * button). | 318 * button). |
229 * | 319 * |
230 * TODO(epoger): We could reduce the amount of code by just setting the | 320 * TODO(epoger): We could reduce the amount of code by just setting the |
231 * variable directly (from, e.g., a button's ng-click handler). But when | 321 * variable directly (from, e.g., a button's ng-click handler). But when |
232 * I tried that, the HTML elements depending on the variable did not get | 322 * I tried that, the HTML elements depending on the variable did not get |
233 * updated. | 323 * updated. |
234 * It turns out that this is due to variable scoping within an ng-repeat | 324 * It turns out that this is due to variable scoping within an ng-repeat |
235 * element; see http://stackoverflow.com/questions/15388344/behavior-of-assi
gnment-expression-invoked-by-ng-click-within-ng-repeat | 325 * element; see http://stackoverflow.com/questions/15388344/behavior-of-assi
gnment-expression-invoked-by-ng-click-within-ng-repeat |
236 * | 326 * |
237 * @param val boolean value to set $scope.areUpdatesPending to | 327 * @param val boolean value to set $scope.areUpdatesPending to |
238 */ | 328 */ |
239 $scope.setUpdatesPending = function(val) { | 329 $scope.setUpdatesPending = function(val) { |
240 $scope.areUpdatesPending = val; | 330 $scope.areUpdatesPending = val; |
241 } | 331 } |
242 | 332 |
243 /** | 333 /** |
244 * Update the displayed results, based on filters/settings. | 334 * Update the displayed results, based on filters/settings, |
| 335 * and call $scope.queryParameters.save() so that the new filter results |
| 336 * can be bookmarked. |
245 */ | 337 */ |
246 $scope.updateResults = function() { | 338 $scope.updateResults = function() { |
247 $scope.displayLimit = $scope.displayLimitPending; | 339 $scope.displayLimit = $scope.displayLimitPending; |
248 // TODO(epoger): Every time we apply a filter, AngularJS creates | 340 // TODO(epoger): Every time we apply a filter, AngularJS creates |
249 // another copy of the array. Is there a way we can filter out | 341 // another copy of the array. Is there a way we can filter out |
250 // the items as they are displayed, rather than storing multiple | 342 // the items as they are displayed, rather than storing multiple |
251 // array copies? (For better performance.) | 343 // array copies? (For better performance.) |
252 | 344 |
253 if ($scope.viewingTab == $scope.defaultTab) { | 345 if ($scope.viewingTab == $scope.defaultTab) { |
254 | 346 |
(...skipping 22 matching lines...) Expand all Loading... |
277 $filter("filter")( | 369 $filter("filter")( |
278 $scope.testData, | 370 $scope.testData, |
279 {tab: $scope.viewingTab}, | 371 {tab: $scope.viewingTab}, |
280 true | 372 true |
281 ), | 373 ), |
282 $scope.sortColumn); | 374 $scope.sortColumn); |
283 $scope.limitedTestData = $scope.filteredTestData; | 375 $scope.limitedTestData = $scope.filteredTestData; |
284 } | 376 } |
285 $scope.imageSize = $scope.imageSizePending; | 377 $scope.imageSize = $scope.imageSizePending; |
286 $scope.setUpdatesPending(false); | 378 $scope.setUpdatesPending(false); |
| 379 $scope.queryParameters.save(); |
287 } | 380 } |
288 | 381 |
289 /** | 382 /** |
290 * Re-sort the displayed results. | 383 * Re-sort the displayed results. |
291 * | 384 * |
292 * @param sortColumn (string): name of the column to sort on | 385 * @param sortColumn (string): name of the column to sort on |
293 */ | 386 */ |
294 $scope.sortResultsBy = function(sortColumn) { | 387 $scope.sortResultsBy = function(sortColumn) { |
295 $scope.sortColumn = sortColumn; | 388 $scope.sortColumn = sortColumn; |
296 $scope.updateResults(); | 389 $scope.updateResults(); |
(...skipping 220 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
517 * | 610 * |
518 * @param secondsPastEpoch (numeric): seconds past epoch in UTC | 611 * @param secondsPastEpoch (numeric): seconds past epoch in UTC |
519 */ | 612 */ |
520 $scope.localTimeString = function(secondsPastEpoch) { | 613 $scope.localTimeString = function(secondsPastEpoch) { |
521 var d = new Date(secondsPastEpoch * 1000); | 614 var d = new Date(secondsPastEpoch * 1000); |
522 return d.toString(); | 615 return d.toString(); |
523 } | 616 } |
524 | 617 |
525 } | 618 } |
526 ); | 619 ); |
OLD | NEW |