| 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.extraColumnHeaders and $scope.imagePairs . | 4 * them into $scope.extraColumnHeaders and $scope.imagePairs . |
| 5 */ | 5 */ |
| 6 var Loader = angular.module( | 6 var Loader = angular.module( |
| 7 'Loader', | 7 'Loader', |
| 8 ['ConstantsModule'] | 8 ['ConstantsModule'] |
| 9 ); | 9 ); |
| 10 | 10 |
| (...skipping 112 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 123 | 123 |
| 124 Loader.controller( | 124 Loader.controller( |
| 125 'Loader.Controller', | 125 'Loader.Controller', |
| 126 function($scope, $http, $filter, $location, $log, $timeout, constants) { | 126 function($scope, $http, $filter, $location, $log, $timeout, constants) { |
| 127 $scope.readyToDisplay = false; | 127 $scope.readyToDisplay = false; |
| 128 $scope.constants = constants; | 128 $scope.constants = constants; |
| 129 $scope.windowTitle = "Loading GM Results..."; | 129 $scope.windowTitle = "Loading GM Results..."; |
| 130 $scope.resultsToLoad = $location.search().resultsToLoad; | 130 $scope.resultsToLoad = $location.search().resultsToLoad; |
| 131 $scope.loadingMessage = "please wait..."; | 131 $scope.loadingMessage = "please wait..."; |
| 132 | 132 |
| 133 var currSortAsc = true; |
| 134 |
| 135 |
| 133 /** | 136 /** |
| 134 * On initial page load, load a full dictionary of results. | 137 * On initial page load, load a full dictionary of results. |
| 135 * Once the dictionary is loaded, unhide the page elements so they can | 138 * Once the dictionary is loaded, unhide the page elements so they can |
| 136 * render the data. | 139 * render the data. |
| 137 */ | 140 */ |
| 138 $http.get($scope.resultsToLoad).success( | 141 $http.get($scope.resultsToLoad).success( |
| 139 function(data, status, header, config) { | 142 function(data, status, header, config) { |
| 140 var dataHeader = data[constants.KEY__ROOT__HEADER]; | 143 var dataHeader = data[constants.KEY__ROOT__HEADER]; |
| 141 if (dataHeader[constants.KEY__HEADER__SCHEMA_VERSION] != | 144 if (dataHeader[constants.KEY__HEADER__SCHEMA_VERSION] != |
| 142 constants.VALUE__HEADER__SCHEMA_VERSION) { | 145 constants.VALUE__HEADER__SCHEMA_VERSION) { |
| (...skipping 17 matching lines...) Expand all Loading... |
| 160 function(){location.reload();}, | 163 function(){location.reload();}, |
| 161 timeToReload - timeNow); | 164 timeToReload - timeNow); |
| 162 } else { | 165 } else { |
| 163 $scope.loadingMessage = "processing data, please wait..."; | 166 $scope.loadingMessage = "processing data, please wait..."; |
| 164 | 167 |
| 165 $scope.header = dataHeader; | 168 $scope.header = dataHeader; |
| 166 $scope.extraColumnHeaders = data[constants.KEY__ROOT__EXTRACOLUMNHEADE
RS]; | 169 $scope.extraColumnHeaders = data[constants.KEY__ROOT__EXTRACOLUMNHEADE
RS]; |
| 167 $scope.orderedColumnNames = data[constants.KEY__ROOT__EXTRACOLUMNORDER
]; | 170 $scope.orderedColumnNames = data[constants.KEY__ROOT__EXTRACOLUMNORDER
]; |
| 168 $scope.imagePairs = data[constants.KEY__ROOT__IMAGEPAIRS]; | 171 $scope.imagePairs = data[constants.KEY__ROOT__IMAGEPAIRS]; |
| 169 $scope.imageSets = data[constants.KEY__ROOT__IMAGESETS]; | 172 $scope.imageSets = data[constants.KEY__ROOT__IMAGESETS]; |
| 173 |
| 174 // set the default sort column and make it ascending. |
| 170 $scope.sortColumnSubdict = constants.KEY__IMAGEPAIRS__DIFFERENCES; | 175 $scope.sortColumnSubdict = constants.KEY__IMAGEPAIRS__DIFFERENCES; |
| 171 $scope.sortColumnKey = constants.KEY__DIFFERENCES__PERCEPTUAL_DIFF; | 176 $scope.sortColumnKey = constants.KEY__DIFFERENCES__PERCEPTUAL_DIFF; |
| 177 currSortAsc = true; |
| 172 | 178 |
| 173 $scope.showSubmitAdvancedSettings = false; | 179 $scope.showSubmitAdvancedSettings = false; |
| 174 $scope.submitAdvancedSettings = {}; | 180 $scope.submitAdvancedSettings = {}; |
| 175 $scope.submitAdvancedSettings[ | 181 $scope.submitAdvancedSettings[ |
| 176 constants.KEY__EXPECTATIONS__REVIEWED] = true; | 182 constants.KEY__EXPECTATIONS__REVIEWED] = true; |
| 177 $scope.submitAdvancedSettings[ | 183 $scope.submitAdvancedSettings[ |
| 178 constants.KEY__EXPECTATIONS__IGNOREFAILURE] = false; | 184 constants.KEY__EXPECTATIONS__IGNOREFAILURE] = false; |
| 179 $scope.submitAdvancedSettings['bug'] = ''; | 185 $scope.submitAdvancedSettings['bug'] = ''; |
| 180 | 186 |
| 181 // Create the list of tabs (lists into which the user can file each | 187 // Create the list of tabs (lists into which the user can file each |
| (...skipping 131 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 313 * Select all currently showing tests. | 319 * Select all currently showing tests. |
| 314 */ | 320 */ |
| 315 $scope.selectAllImagePairs = function() { | 321 $scope.selectAllImagePairs = function() { |
| 316 var numImagePairsShowing = $scope.limitedImagePairs.length; | 322 var numImagePairsShowing = $scope.limitedImagePairs.length; |
| 317 for (var i = 0; i < numImagePairsShowing; i++) { | 323 for (var i = 0; i < numImagePairsShowing; i++) { |
| 318 var index = $scope.limitedImagePairs[i].index; | 324 var index = $scope.limitedImagePairs[i].index; |
| 319 if (!$scope.isValueInArray(index, $scope.selectedImagePairs)) { | 325 if (!$scope.isValueInArray(index, $scope.selectedImagePairs)) { |
| 320 $scope.toggleValueInArray(index, $scope.selectedImagePairs); | 326 $scope.toggleValueInArray(index, $scope.selectedImagePairs); |
| 321 } | 327 } |
| 322 } | 328 } |
| 323 } | 329 }; |
| 324 | 330 |
| 325 /** | 331 /** |
| 326 * Deselect all currently showing tests. | 332 * Deselect all currently showing tests. |
| 327 */ | 333 */ |
| 328 $scope.clearAllImagePairs = function() { | 334 $scope.clearAllImagePairs = function() { |
| 329 var numImagePairsShowing = $scope.limitedImagePairs.length; | 335 var numImagePairsShowing = $scope.limitedImagePairs.length; |
| 330 for (var i = 0; i < numImagePairsShowing; i++) { | 336 for (var i = 0; i < numImagePairsShowing; i++) { |
| 331 var index = $scope.limitedImagePairs[i].index; | 337 var index = $scope.limitedImagePairs[i].index; |
| 332 if ($scope.isValueInArray(index, $scope.selectedImagePairs)) { | 338 if ($scope.isValueInArray(index, $scope.selectedImagePairs)) { |
| 333 $scope.toggleValueInArray(index, $scope.selectedImagePairs); | 339 $scope.toggleValueInArray(index, $scope.selectedImagePairs); |
| 334 } | 340 } |
| 335 } | 341 } |
| 336 } | 342 }; |
| 337 | 343 |
| 338 /** | 344 /** |
| 339 * Toggle selection of all currently showing tests. | 345 * Toggle selection of all currently showing tests. |
| 340 */ | 346 */ |
| 341 $scope.toggleAllImagePairs = function() { | 347 $scope.toggleAllImagePairs = function() { |
| 342 var numImagePairsShowing = $scope.limitedImagePairs.length; | 348 var numImagePairsShowing = $scope.limitedImagePairs.length; |
| 343 for (var i = 0; i < numImagePairsShowing; i++) { | 349 for (var i = 0; i < numImagePairsShowing; i++) { |
| 344 var index = $scope.limitedImagePairs[i].index; | 350 var index = $scope.limitedImagePairs[i].index; |
| 345 $scope.toggleValueInArray(index, $scope.selectedImagePairs); | 351 $scope.toggleValueInArray(index, $scope.selectedImagePairs); |
| 346 } | 352 } |
| 347 } | 353 }; |
| 348 | 354 |
| 349 /** | 355 /** |
| 350 * Toggle selection state of a subset of the currently showing tests. | 356 * Toggle selection state of a subset of the currently showing tests. |
| 351 * | 357 * |
| 352 * @param startIndex index within $scope.limitedImagePairs of the first | 358 * @param startIndex index within $scope.limitedImagePairs of the first |
| 353 * test to toggle selection state of | 359 * test to toggle selection state of |
| 354 * @param num number of tests (in a contiguous block) to toggle | 360 * @param num number of tests (in a contiguous block) to toggle |
| 355 */ | 361 */ |
| 356 $scope.toggleSomeImagePairs = function(startIndex, num) { | 362 $scope.toggleSomeImagePairs = function(startIndex, num) { |
| 357 var numImagePairsShowing = $scope.limitedImagePairs.length; | 363 var numImagePairsShowing = $scope.limitedImagePairs.length; |
| 358 for (var i = startIndex; i < startIndex + num; i++) { | 364 for (var i = startIndex; i < startIndex + num; i++) { |
| 359 var index = $scope.limitedImagePairs[i].index; | 365 var index = $scope.limitedImagePairs[i].index; |
| 360 $scope.toggleValueInArray(index, $scope.selectedImagePairs); | 366 $scope.toggleValueInArray(index, $scope.selectedImagePairs); |
| 361 } | 367 } |
| 362 } | 368 }; |
| 363 | 369 |
| 364 | 370 |
| 365 // | 371 // |
| 366 // Tab operations. | 372 // Tab operations. |
| 367 // | 373 // |
| 368 | 374 |
| 369 /** | 375 /** |
| 370 * Change the selected tab. | 376 * Change the selected tab. |
| 371 * | 377 * |
| 372 * @param tab (string): name of the tab to select | 378 * @param tab (string): name of the tab to select |
| 373 */ | 379 */ |
| 374 $scope.setViewingTab = function(tab) { | 380 $scope.setViewingTab = function(tab) { |
| 375 $scope.viewingTab = tab; | 381 $scope.viewingTab = tab; |
| 376 $scope.updateResults(); | 382 $scope.updateResults(); |
| 377 } | 383 }; |
| 378 | 384 |
| 379 /** | 385 /** |
| 380 * Move the imagePairs in $scope.selectedImagePairs to a different tab, | 386 * Move the imagePairs in $scope.selectedImagePairs to a different tab, |
| 381 * and then clear $scope.selectedImagePairs. | 387 * and then clear $scope.selectedImagePairs. |
| 382 * | 388 * |
| 383 * @param newTab (string): name of the tab to move the tests to | 389 * @param newTab (string): name of the tab to move the tests to |
| 384 */ | 390 */ |
| 385 $scope.moveSelectedImagePairsToTab = function(newTab) { | 391 $scope.moveSelectedImagePairsToTab = function(newTab) { |
| 386 $scope.moveImagePairsToTab($scope.selectedImagePairs, newTab); | 392 $scope.moveImagePairsToTab($scope.selectedImagePairs, newTab); |
| 387 $scope.selectedImagePairs = []; | 393 $scope.selectedImagePairs = []; |
| 388 $scope.updateResults(); | 394 $scope.updateResults(); |
| 389 } | 395 }; |
| 390 | 396 |
| 391 /** | 397 /** |
| 392 * Move a subset of $scope.imagePairs to a different tab. | 398 * Move a subset of $scope.imagePairs to a different tab. |
| 393 * | 399 * |
| 394 * @param imagePairIndices (array of ints): indices into $scope.imagePairs | 400 * @param imagePairIndices (array of ints): indices into $scope.imagePairs |
| 395 * indicating which test results to move | 401 * indicating which test results to move |
| 396 * @param newTab (string): name of the tab to move the tests to | 402 * @param newTab (string): name of the tab to move the tests to |
| 397 */ | 403 */ |
| 398 $scope.moveImagePairsToTab = function(imagePairIndices, newTab) { | 404 $scope.moveImagePairsToTab = function(imagePairIndices, newTab) { |
| 399 var imagePairIndex; | 405 var imagePairIndex; |
| 400 var numImagePairs = imagePairIndices.length; | 406 var numImagePairs = imagePairIndices.length; |
| 401 for (var i = 0; i < numImagePairs; i++) { | 407 for (var i = 0; i < numImagePairs; i++) { |
| 402 imagePairIndex = imagePairIndices[i]; | 408 imagePairIndex = imagePairIndices[i]; |
| 403 $scope.numResultsPerTab[$scope.imagePairs[imagePairIndex].tab]--; | 409 $scope.numResultsPerTab[$scope.imagePairs[imagePairIndex].tab]--; |
| 404 $scope.imagePairs[imagePairIndex].tab = newTab; | 410 $scope.imagePairs[imagePairIndex].tab = newTab; |
| 405 } | 411 } |
| 406 $scope.numResultsPerTab[newTab] += numImagePairs; | 412 $scope.numResultsPerTab[newTab] += numImagePairs; |
| 407 } | 413 }; |
| 408 | 414 |
| 409 | 415 |
| 410 // | 416 // |
| 411 // $scope.queryParameters: | 417 // $scope.queryParameters: |
| 412 // Transfer parameter values between $scope and the URL query string. | 418 // Transfer parameter values between $scope and the URL query string. |
| 413 // | 419 // |
| 414 $scope.queryParameters = {}; | 420 $scope.queryParameters = {}; |
| 415 | 421 |
| 416 // load and save functions for parameters of each type | 422 // load and save functions for parameters of each type |
| 417 // (load a parameter value into $scope from nameValuePairs, | 423 // (load a parameter value into $scope from nameValuePairs, |
| (...skipping 172 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 590 ); | 596 ); |
| 591 $scope.showingColumnValues[columnName] = showingColumnValues; | 597 $scope.showingColumnValues[columnName] = showingColumnValues; |
| 592 } | 598 } |
| 593 } | 599 } |
| 594 ); | 600 ); |
| 595 | 601 |
| 596 // TODO(epoger): Every time we apply a filter, AngularJS creates | 602 // TODO(epoger): Every time we apply a filter, AngularJS creates |
| 597 // another copy of the array. Is there a way we can filter out | 603 // another copy of the array. Is there a way we can filter out |
| 598 // the imagePairs as they are displayed, rather than storing multiple | 604 // the imagePairs as they are displayed, rather than storing multiple |
| 599 // array copies? (For better performance.) | 605 // array copies? (For better performance.) |
| 600 | |
| 601 if ($scope.viewingTab == $scope.defaultTab) { | 606 if ($scope.viewingTab == $scope.defaultTab) { |
| 602 | 607 var doReverse = !currSortAsc; |
| 603 // TODO(epoger): Until we allow the user to reverse sort order, | |
| 604 // there are certain columns we want to sort in a different order. | |
| 605 var doReverse = ( | |
| 606 ($scope.sortColumnKey == | |
| 607 constants.KEY__DIFFERENCES__PERCENT_DIFF_PIXELS) || | |
| 608 ($scope.sortColumnKey == | |
| 609 constants.KEY__DIFFERENCES__PERCEPTUAL_DIFF)); | |
| 610 | 608 |
| 611 $scope.filteredImagePairs = | 609 $scope.filteredImagePairs = |
| 612 $filter("orderBy")( | 610 $filter("orderBy")( |
| 613 $filter("removeHiddenImagePairs")( | 611 $filter("removeHiddenImagePairs")( |
| 614 $scope.imagePairs, | 612 $scope.imagePairs, |
| 615 $scope.filterableColumnNames, | 613 $scope.filterableColumnNames, |
| 616 $scope.showingColumnValues, | 614 $scope.showingColumnValues, |
| 617 $scope.viewingTab | 615 $scope.viewingTab |
| 618 ), | 616 ), |
| 619 [$scope.getSortColumnValue, $scope.getSecondOrderSortValue], | 617 // [$scope.getSortColumnValue, $scope.getSecondOrderSortValue], |
| 618 $scope.getSortColumnValue, |
| 620 doReverse); | 619 doReverse); |
| 621 $scope.limitedImagePairs = $filter("mergeAndLimit")( | 620 $scope.limitedImagePairs = $filter("mergeAndLimit")( |
| 622 $scope.filteredImagePairs, $scope.displayLimit, $scope.mergeIdentica
lRows); | 621 $scope.filteredImagePairs, $scope.displayLimit, $scope.mergeIdentica
lRows); |
| 623 } else { | 622 } else { |
| 624 $scope.filteredImagePairs = | 623 $scope.filteredImagePairs = |
| 625 $filter("orderBy")( | 624 $filter("orderBy")( |
| 626 $filter("filter")( | 625 $filter("filter")( |
| 627 $scope.imagePairs, | 626 $scope.imagePairs, |
| 628 {tab: $scope.viewingTab}, | 627 {tab: $scope.viewingTab}, |
| 629 true | 628 true |
| 630 ), | 629 ), |
| 631 [$scope.getSortColumnValue, $scope.getSecondOrderSortValue]); | 630 // [$scope.getSortColumnValue, $scope.getSecondOrderSortValue]); |
| 631 $scope.getSortColumnValue); |
| 632 $scope.limitedImagePairs = $filter("mergeAndLimit")( | 632 $scope.limitedImagePairs = $filter("mergeAndLimit")( |
| 633 $scope.filteredImagePairs, -1, $scope.mergeIdenticalRows); | 633 $scope.filteredImagePairs, -1, $scope.mergeIdenticalRows); |
| 634 } | 634 } |
| 635 $scope.showThumbnails = $scope.showThumbnailsPending; | 635 $scope.showThumbnails = $scope.showThumbnailsPending; |
| 636 $scope.imageSize = $scope.imageSizePending; | 636 $scope.imageSize = $scope.imageSizePending; |
| 637 $scope.setUpdatesPending(false); | 637 $scope.setUpdatesPending(false); |
| 638 $scope.queryParameters.save(); | 638 $scope.queryParameters.save(); |
| 639 } | 639 } |
| 640 | 640 |
| 641 /** | 641 /** |
| 642 * This function is called when the results have been completely rendered | 642 * This function is called when the results have been completely rendered |
| 643 * after updateResults(). | 643 * after updateResults(). |
| 644 */ | 644 */ |
| 645 $scope.resultsUpdatedCallback = function() { | 645 $scope.resultsUpdatedCallback = function() { |
| 646 $scope.renderEndTime = window.performance.now(); | 646 $scope.renderEndTime = window.performance.now(); |
| 647 $log.debug("renderEndTime: " + $scope.renderEndTime); | 647 $log.debug("renderEndTime: " + $scope.renderEndTime); |
| 648 } | 648 }; |
| 649 | 649 |
| 650 /** | 650 /** |
| 651 * Re-sort the displayed results. | 651 * Re-sort the displayed results. |
| 652 * | 652 * |
| 653 * @param subdict (string): which KEY__IMAGEPAIRS__* subdictionary | 653 * @param subdict (string): which KEY__IMAGEPAIRS__* subdictionary |
| 654 * the sort column key is within, or 'none' if the sort column | 654 * the sort column key is within, or 'none' if the sort column |
| 655 * key is one of KEY__IMAGEPAIRS__* | 655 * key is one of KEY__IMAGEPAIRS__* |
| 656 * @param key (string): sort by value associated with this key in subdict | 656 * @param key (string): sort by value associated with this key in subdict |
| 657 */ | 657 */ |
| 658 $scope.sortResultsBy = function(subdict, key) { | 658 $scope.sortResultsBy = function(subdict, key) { |
| 659 $scope.sortColumnSubdict = subdict; | 659 // if we are already sorting by this column then toggle between asc/desc |
| 660 $scope.sortColumnKey = key; | 660 if ((subdict === $scope.sortColumnSubdict) && ($scope.sortColumnKey === ke
y)) { |
| 661 currSortAsc = !currSortAsc; |
| 662 } else { |
| 663 $scope.sortColumnSubdict = subdict; |
| 664 $scope.sortColumnKey = key; |
| 665 currSortAsc = true; |
| 666 } |
| 661 $scope.updateResults(); | 667 $scope.updateResults(); |
| 662 } | 668 }; |
| 669 |
| 670 /** |
| 671 * Returns ASC or DESC (from constants) if currently the data |
| 672 * is sorted by the provided column. |
| 673 * |
| 674 * @param colName: name of the column for which we need to get the class. |
| 675 */ |
| 676 |
| 677 $scope.sortedByColumnsCls = function (colName) { |
| 678 if ($scope.sortColumnKey !== colName) { |
| 679 return ''; |
| 680 } |
| 681 |
| 682 var result = (currSortAsc) ? constants.ASC : constants.DESC; |
| 683 console.log("sort class:", result); |
| 684 return result; |
| 685 }; |
| 663 | 686 |
| 664 /** | 687 /** |
| 665 * For a particular ImagePair, return the value of the column we are | 688 * For a particular ImagePair, return the value of the column we are |
| 666 * sorting on (according to $scope.sortColumnSubdict and | 689 * sorting on (according to $scope.sortColumnSubdict and |
| 667 * $scope.sortColumnKey). | 690 * $scope.sortColumnKey). |
| 668 * | 691 * |
| 669 * @param imagePair: imagePair to get a column value out of. | 692 * @param imagePair: imagePair to get a column value out of. |
| 670 */ | 693 */ |
| 671 $scope.getSortColumnValue = function(imagePair) { | 694 $scope.getSortColumnValue = function(imagePair) { |
| 672 if ($scope.sortColumnSubdict in imagePair) { | 695 if ($scope.sortColumnSubdict in imagePair) { |
| 673 return imagePair[$scope.sortColumnSubdict][$scope.sortColumnKey]; | 696 return imagePair[$scope.sortColumnSubdict][$scope.sortColumnKey]; |
| 674 } else if ($scope.sortColumnKey in imagePair) { | 697 } else if ($scope.sortColumnKey in imagePair) { |
| 675 return imagePair[$scope.sortColumnKey]; | 698 return imagePair[$scope.sortColumnKey]; |
| 676 } else { | 699 } else { |
| 677 return undefined; | 700 return undefined; |
| 678 } | 701 } |
| 679 } | 702 }; |
| 680 | 703 |
| 681 /** | 704 /** |
| 682 * For a particular ImagePair, return the value we use for the | 705 * For a particular ImagePair, return the value we use for the |
| 683 * second-order sort (tiebreaker when multiple rows have | 706 * second-order sort (tiebreaker when multiple rows have |
| 684 * the same getSortColumnValue()). | 707 * the same getSortColumnValue()). |
| 685 * | 708 * |
| 686 * We join the imageA and imageB urls for this value, so that we merge | 709 * We join the imageA and imageB urls for this value, so that we merge |
| 687 * adjacent rows as much as possible. | 710 * adjacent rows as much as possible. |
| 688 * | 711 * |
| 689 * @param imagePair: imagePair to get a column value out of. | 712 * @param imagePair: imagePair to get a column value out of. |
| 690 */ | 713 */ |
| 691 $scope.getSecondOrderSortValue = function(imagePair) { | 714 $scope.getSecondOrderSortValue = function(imagePair) { |
| 692 return imagePair[constants.KEY__IMAGEPAIRS__IMAGE_A_URL] + "-vs-" + | 715 return imagePair[constants.KEY__IMAGEPAIRS__IMAGE_A_URL] + "-vs-" + |
| 693 imagePair[constants.KEY__IMAGEPAIRS__IMAGE_B_URL]; | 716 imagePair[constants.KEY__IMAGEPAIRS__IMAGE_B_URL]; |
| 694 } | 717 }; |
| 695 | 718 |
| 696 /** | 719 /** |
| 697 * Set $scope.columnStringMatch[name] = value, and update results. | 720 * Set $scope.columnStringMatch[name] = value, and update results. |
| 698 * | 721 * |
| 699 * @param name | 722 * @param name |
| 700 * @param value | 723 * @param value |
| 701 */ | 724 */ |
| 702 $scope.setColumnStringMatch = function(name, value) { | 725 $scope.setColumnStringMatch = function(name, value) { |
| 703 $scope.columnStringMatch[name] = value; | 726 $scope.columnStringMatch[name] = value; |
| 704 $scope.updateResults(); | 727 $scope.updateResults(); |
| 705 } | 728 }; |
| 706 | 729 |
| 707 /** | 730 /** |
| 708 * Update $scope.showingColumnValues[columnName] and $scope.columnStringMatc
h[columnName] | 731 * Update $scope.showingColumnValues[columnName] and $scope.columnStringMatc
h[columnName] |
| 709 * so that ONLY entries with this columnValue are showing, and update the vi
sible results. | 732 * so that ONLY entries with this columnValue are showing, and update the vi
sible results. |
| 710 * (We update both of those, so we cover both freeform and checkbox filtered
columns.) | 733 * (We update both of those, so we cover both freeform and checkbox filtered
columns.) |
| 711 * | 734 * |
| 712 * @param columnName | 735 * @param columnName |
| 713 * @param columnValue | 736 * @param columnValue |
| 714 */ | 737 */ |
| 715 $scope.showOnlyColumnValue = function(columnName, columnValue) { | 738 $scope.showOnlyColumnValue = function(columnName, columnValue) { |
| 716 $scope.columnStringMatch[columnName] = columnValue; | 739 $scope.columnStringMatch[columnName] = columnValue; |
| 717 $scope.showingColumnValues[columnName] = {}; | 740 $scope.showingColumnValues[columnName] = {}; |
| 718 $scope.toggleValueInSet(columnValue, $scope.showingColumnValues[columnName
]); | 741 $scope.toggleValueInSet(columnValue, $scope.showingColumnValues[columnName
]); |
| 719 $scope.updateResults(); | 742 $scope.updateResults(); |
| 720 } | 743 }; |
| 721 | 744 |
| 722 /** | 745 /** |
| 723 * Update $scope.showingColumnValues[columnName] and $scope.columnStringMatc
h[columnName] | 746 * Update $scope.showingColumnValues[columnName] and $scope.columnStringMatc
h[columnName] |
| 724 * so that ALL entries are showing, and update the visible results. | 747 * so that ALL entries are showing, and update the visible results. |
| 725 * (We update both of those, so we cover both freeform and checkbox filtered
columns.) | 748 * (We update both of those, so we cover both freeform and checkbox filtered
columns.) |
| 726 * | 749 * |
| 727 * @param columnName | 750 * @param columnName |
| 728 */ | 751 */ |
| 729 $scope.showAllColumnValues = function(columnName) { | 752 $scope.showAllColumnValues = function(columnName) { |
| 730 $scope.columnStringMatch[columnName] = ""; | 753 $scope.columnStringMatch[columnName] = ""; |
| 731 $scope.showingColumnValues[columnName] = {}; | 754 $scope.showingColumnValues[columnName] = {}; |
| 732 $scope.toggleValuesInSet($scope.allColumnValues[columnName], | 755 $scope.toggleValuesInSet($scope.allColumnValues[columnName], |
| 733 $scope.showingColumnValues[columnName]); | 756 $scope.showingColumnValues[columnName]); |
| 734 $scope.updateResults(); | 757 $scope.updateResults(); |
| 735 } | 758 }; |
| 736 | 759 |
| 737 | 760 |
| 738 // | 761 // |
| 739 // Operations for sending info back to the server. | 762 // Operations for sending info back to the server. |
| 740 // | 763 // |
| 741 | 764 |
| 742 /** | 765 /** |
| 743 * Tell the server that the actual results of these particular tests | 766 * Tell the server that the actual results of these particular tests |
| 744 * are acceptable. | 767 * are acceptable. |
| 745 * | 768 * |
| (...skipping 89 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 835 "finished loading the update results into memory!) and you can " + | 858 "finished loading the update results into memory!) and you can " + |
| 836 "submit more baselines if you want."); | 859 "submit more baselines if you want."); |
| 837 // I don't know why, but if I just call reload() here it doesn't work. | 860 // I don't know why, but if I just call reload() here it doesn't work. |
| 838 // Making a timer call it fixes the problem. | 861 // Making a timer call it fixes the problem. |
| 839 $timeout(function(){location.reload();}, 1); | 862 $timeout(function(){location.reload();}, 1); |
| 840 }).error(function(data, status, headers, config) { | 863 }).error(function(data, status, headers, config) { |
| 841 alert("There was an error submitting your baselines.\n\n" + | 864 alert("There was an error submitting your baselines.\n\n" + |
| 842 "Please see server-side log for details."); | 865 "Please see server-side log for details."); |
| 843 $scope.submitPending = false; | 866 $scope.submitPending = false; |
| 844 }); | 867 }); |
| 845 } | 868 }; |
| 846 | 869 |
| 847 | 870 |
| 848 // | 871 // |
| 849 // Operations we use to mimic Set semantics, in such a way that | 872 // Operations we use to mimic Set semantics, in such a way that |
| 850 // checking for presence within the Set is as fast as possible. | 873 // checking for presence within the Set is as fast as possible. |
| 851 // But getting a list of all values within the Set is not necessarily | 874 // But getting a list of all values within the Set is not necessarily |
| 852 // possible. | 875 // possible. |
| 853 // TODO(epoger): move into a separate .js file? | 876 // TODO(epoger): move into a separate .js file? |
| 854 // | 877 // |
| 855 | 878 |
| 856 /** | 879 /** |
| 857 * Returns the number of values present within set "set". | 880 * Returns the number of values present within set "set". |
| 858 * | 881 * |
| 859 * @param set an Object which we use to mimic set semantics | 882 * @param set an Object which we use to mimic set semantics |
| 860 */ | 883 */ |
| 861 $scope.setSize = function(set) { | 884 $scope.setSize = function(set) { |
| 862 return Object.keys(set).length; | 885 return Object.keys(set).length; |
| 863 } | 886 }; |
| 864 | 887 |
| 865 /** | 888 /** |
| 866 * Returns true if value "value" is present within set "set". | 889 * Returns true if value "value" is present within set "set". |
| 867 * | 890 * |
| 868 * @param value a value of any type | 891 * @param value a value of any type |
| 869 * @param set an Object which we use to mimic set semantics | 892 * @param set an Object which we use to mimic set semantics |
| 870 * (this should make isValueInSet faster than if we used an Array) | 893 * (this should make isValueInSet faster than if we used an Array) |
| 871 */ | 894 */ |
| 872 $scope.isValueInSet = function(value, set) { | 895 $scope.isValueInSet = function(value, set) { |
| 873 return (true == set[value]); | 896 return (true == set[value]); |
| 874 } | 897 }; |
| 875 | 898 |
| 876 /** | 899 /** |
| 877 * If value "value" is already in set "set", remove it; otherwise, add it. | 900 * If value "value" is already in set "set", remove it; otherwise, add it. |
| 878 * | 901 * |
| 879 * @param value a value of any type | 902 * @param value a value of any type |
| 880 * @param set an Object which we use to mimic set semantics | 903 * @param set an Object which we use to mimic set semantics |
| 881 */ | 904 */ |
| 882 $scope.toggleValueInSet = function(value, set) { | 905 $scope.toggleValueInSet = function(value, set) { |
| 883 if (true == set[value]) { | 906 if (true == set[value]) { |
| 884 delete set[value]; | 907 delete set[value]; |
| 885 } else { | 908 } else { |
| 886 set[value] = true; | 909 set[value] = true; |
| 887 } | 910 } |
| 888 } | 911 }; |
| 889 | 912 |
| 890 /** | 913 /** |
| 891 * For each value in valueArray, call toggleValueInSet(value, set). | 914 * For each value in valueArray, call toggleValueInSet(value, set). |
| 892 * | 915 * |
| 893 * @param valueArray | 916 * @param valueArray |
| 894 * @param set | 917 * @param set |
| 895 */ | 918 */ |
| 896 $scope.toggleValuesInSet = function(valueArray, set) { | 919 $scope.toggleValuesInSet = function(valueArray, set) { |
| 897 var arrayLength = valueArray.length; | 920 var arrayLength = valueArray.length; |
| 898 for (var i = 0; i < arrayLength; i++) { | 921 for (var i = 0; i < arrayLength; i++) { |
| 899 $scope.toggleValueInSet(valueArray[i], set); | 922 $scope.toggleValueInSet(valueArray[i], set); |
| 900 } | 923 } |
| 901 } | 924 }; |
| 902 | 925 |
| 903 | 926 |
| 904 // | 927 // |
| 905 // Array operations; similar to our Set operations, but operate on a | 928 // Array operations; similar to our Set operations, but operate on a |
| 906 // Javascript Array so we *can* easily get a list of all values in the Set. | 929 // Javascript Array so we *can* easily get a list of all values in the Set. |
| 907 // TODO(epoger): move into a separate .js file? | 930 // TODO(epoger): move into a separate .js file? |
| 908 // | 931 // |
| 909 | 932 |
| 910 /** | 933 /** |
| 911 * Returns true if value "value" is present within array "array". | 934 * Returns true if value "value" is present within array "array". |
| 912 * | 935 * |
| 913 * @param value a value of any type | 936 * @param value a value of any type |
| 914 * @param array a Javascript Array | 937 * @param array a Javascript Array |
| 915 */ | 938 */ |
| 916 $scope.isValueInArray = function(value, array) { | 939 $scope.isValueInArray = function(value, array) { |
| 917 return (-1 != array.indexOf(value)); | 940 return (-1 != array.indexOf(value)); |
| 918 } | 941 }; |
| 919 | 942 |
| 920 /** | 943 /** |
| 921 * If value "value" is already in array "array", remove it; otherwise, | 944 * If value "value" is already in array "array", remove it; otherwise, |
| 922 * add it. | 945 * add it. |
| 923 * | 946 * |
| 924 * @param value a value of any type | 947 * @param value a value of any type |
| 925 * @param array a Javascript Array | 948 * @param array a Javascript Array |
| 926 */ | 949 */ |
| 927 $scope.toggleValueInArray = function(value, array) { | 950 $scope.toggleValueInArray = function(value, array) { |
| 928 var i = array.indexOf(value); | 951 var i = array.indexOf(value); |
| 929 if (-1 == i) { | 952 if (-1 == i) { |
| 930 array.push(value); | 953 array.push(value); |
| 931 } else { | 954 } else { |
| 932 array.splice(i, 1); | 955 array.splice(i, 1); |
| 933 } | 956 } |
| 934 } | 957 }; |
| 935 | 958 |
| 936 | 959 |
| 937 // | 960 // |
| 938 // Miscellaneous utility functions. | 961 // Miscellaneous utility functions. |
| 939 // TODO(epoger): move into a separate .js file? | 962 // TODO(epoger): move into a separate .js file? |
| 940 // | 963 // |
| 941 | 964 |
| 942 /** | 965 /** |
| 943 * Returns a single "column slice" of a 2D array. | 966 * Returns a single "column slice" of a 2D array. |
| 944 * | 967 * |
| 945 * For example, if array is: | 968 * For example, if array is: |
| 946 * [[A0, A1], | 969 * [[A0, A1], |
| 947 * [B0, B1], | 970 * [B0, B1], |
| 948 * [C0, C1]] | 971 * [C0, C1]] |
| 949 * and index is 0, this this will return: | 972 * and index is 0, this this will return: |
| 950 * [A0, B0, C0] | 973 * [A0, B0, C0] |
| 951 * | 974 * |
| 952 * @param array a Javascript Array | 975 * @param array a Javascript Array |
| 953 * @param column (numeric): index within each row array | 976 * @param column (numeric): index within each row array |
| 954 */ | 977 */ |
| 955 $scope.columnSliceOf2DArray = function(array, column) { | 978 $scope.columnSliceOf2DArray = function(array, column) { |
| 956 var slice = []; | 979 var slice = []; |
| 957 var numRows = array.length; | 980 var numRows = array.length; |
| 958 for (var row = 0; row < numRows; row++) { | 981 for (var row = 0; row < numRows; row++) { |
| 959 slice.push(array[row][column]); | 982 slice.push(array[row][column]); |
| 960 } | 983 } |
| 961 return slice; | 984 return slice; |
| 962 } | 985 }; |
| 963 | 986 |
| 964 /** | 987 /** |
| 965 * Returns a human-readable (in local time zone) time string for a | 988 * Returns a human-readable (in local time zone) time string for a |
| 966 * particular moment in time. | 989 * particular moment in time. |
| 967 * | 990 * |
| 968 * @param secondsPastEpoch (numeric): seconds past epoch in UTC | 991 * @param secondsPastEpoch (numeric): seconds past epoch in UTC |
| 969 */ | 992 */ |
| 970 $scope.localTimeString = function(secondsPastEpoch) { | 993 $scope.localTimeString = function(secondsPastEpoch) { |
| 971 var d = new Date(secondsPastEpoch * 1000); | 994 var d = new Date(secondsPastEpoch * 1000); |
| 972 return d.toString(); | 995 return d.toString(); |
| 973 } | 996 }; |
| 974 | 997 |
| 975 /** | 998 /** |
| 976 * Returns a hex color string (such as "#aabbcc") for the given RGB values. | 999 * Returns a hex color string (such as "#aabbcc") for the given RGB values. |
| 977 * | 1000 * |
| 978 * @param r (numeric): red channel value, 0-255 | 1001 * @param r (numeric): red channel value, 0-255 |
| 979 * @param g (numeric): green channel value, 0-255 | 1002 * @param g (numeric): green channel value, 0-255 |
| 980 * @param b (numeric): blue channel value, 0-255 | 1003 * @param b (numeric): blue channel value, 0-255 |
| 981 */ | 1004 */ |
| 982 $scope.hexColorString = function(r, g, b) { | 1005 $scope.hexColorString = function(r, g, b) { |
| 983 var rString = r.toString(16); | 1006 var rString = r.toString(16); |
| 984 if (r < 16) { | 1007 if (r < 16) { |
| 985 rString = "0" + rString; | 1008 rString = "0" + rString; |
| 986 } | 1009 } |
| 987 var gString = g.toString(16); | 1010 var gString = g.toString(16); |
| 988 if (g < 16) { | 1011 if (g < 16) { |
| 989 gString = "0" + gString; | 1012 gString = "0" + gString; |
| 990 } | 1013 } |
| 991 var bString = b.toString(16); | 1014 var bString = b.toString(16); |
| 992 if (b < 16) { | 1015 if (b < 16) { |
| 993 bString = "0" + bString; | 1016 bString = "0" + bString; |
| 994 } | 1017 } |
| 995 return '#' + rString + gString + bString; | 1018 return '#' + rString + gString + bString; |
| 996 } | 1019 }; |
| 997 | 1020 |
| 998 /** | 1021 /** |
| 999 * Returns a hex color string (such as "#aabbcc") for the given brightness. | 1022 * Returns a hex color string (such as "#aabbcc") for the given brightness. |
| 1000 * | 1023 * |
| 1001 * @param brightnessString (string): 0-255, 0 is completely black | 1024 * @param brightnessString (string): 0-255, 0 is completely black |
| 1002 * | 1025 * |
| 1003 * TODO(epoger): It might be nice to tint the color when it's not completely | 1026 * TODO(epoger): It might be nice to tint the color when it's not completely |
| 1004 * black or completely white. | 1027 * black or completely white. |
| 1005 */ | 1028 */ |
| 1006 $scope.brightnessStringToHexColor = function(brightnessString) { | 1029 $scope.brightnessStringToHexColor = function(brightnessString) { |
| 1007 var v = parseInt(brightnessString); | 1030 var v = parseInt(brightnessString); |
| 1008 return $scope.hexColorString(v, v, v); | 1031 return $scope.hexColorString(v, v, v); |
| 1009 } | 1032 }; |
| 1010 | 1033 |
| 1011 /** | 1034 /** |
| 1012 * Returns the last path component of image diff URL for a given ImagePair. | 1035 * Returns the last path component of image diff URL for a given ImagePair. |
| 1013 * | 1036 * |
| 1014 * Depending on which diff this is (whitediffs, pixeldiffs, etc.) this | 1037 * Depending on which diff this is (whitediffs, pixeldiffs, etc.) this |
| 1015 * will be relative to different base URLs. | 1038 * will be relative to different base URLs. |
| 1016 * | 1039 * |
| 1017 * We must keep this function in sync with _get_difference_locator() in | 1040 * We must keep this function in sync with _get_difference_locator() in |
| 1018 * ../imagediffdb.py | 1041 * ../imagediffdb.py |
| 1019 * | 1042 * |
| 1020 * @param imagePair: ImagePair to generate image diff URL for | 1043 * @param imagePair: ImagePair to generate image diff URL for |
| 1021 */ | 1044 */ |
| 1022 $scope.getImageDiffRelativeUrl = function(imagePair) { | 1045 $scope.getImageDiffRelativeUrl = function(imagePair) { |
| 1023 var before = | 1046 var before = |
| 1024 imagePair[constants.KEY__IMAGEPAIRS__IMAGE_A_URL] + "-vs-" + | 1047 imagePair[constants.KEY__IMAGEPAIRS__IMAGE_A_URL] + "-vs-" + |
| 1025 imagePair[constants.KEY__IMAGEPAIRS__IMAGE_B_URL]; | 1048 imagePair[constants.KEY__IMAGEPAIRS__IMAGE_B_URL]; |
| 1026 return before.replace(/[^\w\-]/g, "_") + ".png"; | 1049 return before.replace(/[^\w\-]/g, "_") + ".png"; |
| 1027 } | 1050 }; |
| 1028 | 1051 |
| 1029 } | 1052 } |
| 1030 ); | 1053 ); |
| OLD | NEW |