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 648 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
659 | 659 |
660 /** | 660 /** |
661 * Re-sort the displayed results. | 661 * Re-sort the displayed results. |
662 * | 662 * |
663 * @param subdict (string): which KEY__IMAGEPAIRS__* subdictionary | 663 * @param subdict (string): which KEY__IMAGEPAIRS__* subdictionary |
664 * the sort column key is within, or 'none' if the sort column | 664 * the sort column key is within, or 'none' if the sort column |
665 * key is one of KEY__IMAGEPAIRS__* | 665 * key is one of KEY__IMAGEPAIRS__* |
666 * @param key (string): sort by value associated with this key in subdict | 666 * @param key (string): sort by value associated with this key in subdict |
667 */ | 667 */ |
668 $scope.sortResultsBy = function(subdict, key) { | 668 $scope.sortResultsBy = function(subdict, key) { |
669 $scope.sortColumnSubdict = subdict; | 669 // if we are already sorting by this column then toggle between asc/desc |
670 $scope.sortColumnKey = key; | 670 if ((subdict === $scope.sortColumnSubdict) && ($scope.sortColumnKey === ke
y)) { |
| 671 currSortAsc = !currSortAsc; |
| 672 } else { |
| 673 $scope.sortColumnSubdict = subdict; |
| 674 $scope.sortColumnKey = key; |
| 675 currSortAsc = true; |
| 676 } |
671 $scope.updateResults(); | 677 $scope.updateResults(); |
672 } | 678 } |
673 | 679 |
674 /** | 680 /** |
| 681 * Returns ASC or DESC (from constants) if currently the data |
| 682 * is sorted by the provided column. |
| 683 * |
| 684 * @param colName: name of the column for which we need to get the class. |
| 685 */ |
| 686 |
| 687 $scope.sortedByColumnsCls = function (colName) { |
| 688 if ($scope.sortColumnKey !== colName) { |
| 689 return ''; |
| 690 } |
| 691 |
| 692 var result = (currSortAsc) ? constants.ASC : constants.DESC; |
| 693 console.log("sort class:", result); |
| 694 return result; |
| 695 }; |
| 696 |
| 697 /** |
675 * For a particular ImagePair, return the value of the column we are | 698 * For a particular ImagePair, return the value of the column we are |
676 * sorting on (according to $scope.sortColumnSubdict and | 699 * sorting on (according to $scope.sortColumnSubdict and |
677 * $scope.sortColumnKey). | 700 * $scope.sortColumnKey). |
678 * | 701 * |
679 * @param imagePair: imagePair to get a column value out of. | 702 * @param imagePair: imagePair to get a column value out of. |
680 */ | 703 */ |
681 $scope.getSortColumnValue = function(imagePair) { | 704 $scope.getSortColumnValue = function(imagePair) { |
682 if ($scope.sortColumnSubdict in imagePair) { | 705 if ($scope.sortColumnSubdict in imagePair) { |
683 return imagePair[$scope.sortColumnSubdict][$scope.sortColumnKey]; | 706 return imagePair[$scope.sortColumnSubdict][$scope.sortColumnKey]; |
684 } else if ($scope.sortColumnKey in imagePair) { | 707 } else if ($scope.sortColumnKey in imagePair) { |
685 return imagePair[$scope.sortColumnKey]; | 708 return imagePair[$scope.sortColumnKey]; |
686 } else { | 709 } else { |
687 return undefined; | 710 return undefined; |
688 } | 711 } |
689 } | 712 }; |
690 | 713 |
691 /** | 714 /** |
692 * For a particular ImagePair, return the value we use for the | 715 * For a particular ImagePair, return the value we use for the |
693 * second-order sort (tiebreaker when multiple rows have | 716 * second-order sort (tiebreaker when multiple rows have |
694 * the same getSortColumnValue()). | 717 * the same getSortColumnValue()). |
695 * | 718 * |
696 * We join the imageA and imageB urls for this value, so that we merge | 719 * We join the imageA and imageB urls for this value, so that we merge |
697 * adjacent rows as much as possible. | 720 * adjacent rows as much as possible. |
698 * | 721 * |
699 * @param imagePair: imagePair to get a column value out of. | 722 * @param imagePair: imagePair to get a column value out of. |
700 */ | 723 */ |
701 $scope.getSecondOrderSortValue = function(imagePair) { | 724 $scope.getSecondOrderSortValue = function(imagePair) { |
702 return imagePair[constants.KEY__IMAGEPAIRS__IMAGE_A_URL] + "-vs-" + | 725 return imagePair[constants.KEY__IMAGEPAIRS__IMAGE_A_URL] + "-vs-" + |
703 imagePair[constants.KEY__IMAGEPAIRS__IMAGE_B_URL]; | 726 imagePair[constants.KEY__IMAGEPAIRS__IMAGE_B_URL]; |
704 } | 727 }; |
705 | 728 |
706 /** | 729 /** |
707 * Set $scope.columnStringMatch[name] = value, and update results. | 730 * Set $scope.columnStringMatch[name] = value, and update results. |
708 * | 731 * |
709 * @param name | 732 * @param name |
710 * @param value | 733 * @param value |
711 */ | 734 */ |
712 $scope.setColumnStringMatch = function(name, value) { | 735 $scope.setColumnStringMatch = function(name, value) { |
713 $scope.columnStringMatch[name] = value; | 736 $scope.columnStringMatch[name] = value; |
714 $scope.updateResults(); | 737 $scope.updateResults(); |
715 } | 738 }; |
716 | 739 |
717 /** | 740 /** |
718 * Update $scope.showingColumnValues[columnName] and $scope.columnStringMatc
h[columnName] | 741 * Update $scope.showingColumnValues[columnName] and $scope.columnStringMatc
h[columnName] |
719 * so that ONLY entries with this columnValue are showing, and update the vi
sible results. | 742 * so that ONLY entries with this columnValue are showing, and update the vi
sible results. |
720 * (We update both of those, so we cover both freeform and checkbox filtered
columns.) | 743 * (We update both of those, so we cover both freeform and checkbox filtered
columns.) |
721 * | 744 * |
722 * @param columnName | 745 * @param columnName |
723 * @param columnValue | 746 * @param columnValue |
724 */ | 747 */ |
725 $scope.showOnlyColumnValue = function(columnName, columnValue) { | 748 $scope.showOnlyColumnValue = function(columnName, columnValue) { |
726 $scope.columnStringMatch[columnName] = columnValue; | 749 $scope.columnStringMatch[columnName] = columnValue; |
727 $scope.showingColumnValues[columnName] = {}; | 750 $scope.showingColumnValues[columnName] = {}; |
728 $scope.toggleValueInSet(columnValue, $scope.showingColumnValues[columnName
]); | 751 $scope.toggleValueInSet(columnValue, $scope.showingColumnValues[columnName
]); |
729 $scope.updateResults(); | 752 $scope.updateResults(); |
730 } | 753 }; |
731 | 754 |
732 /** | 755 /** |
733 * Update $scope.showingColumnValues[columnName] and $scope.columnStringMatc
h[columnName] | 756 * Update $scope.showingColumnValues[columnName] and $scope.columnStringMatc
h[columnName] |
734 * so that ALL entries are showing, and update the visible results. | 757 * so that ALL entries are showing, and update the visible results. |
735 * (We update both of those, so we cover both freeform and checkbox filtered
columns.) | 758 * (We update both of those, so we cover both freeform and checkbox filtered
columns.) |
736 * | 759 * |
737 * @param columnName | 760 * @param columnName |
738 */ | 761 */ |
739 $scope.showAllColumnValues = function(columnName) { | 762 $scope.showAllColumnValues = function(columnName) { |
740 $scope.columnStringMatch[columnName] = ""; | 763 $scope.columnStringMatch[columnName] = ""; |
741 $scope.showingColumnValues[columnName] = {}; | 764 $scope.showingColumnValues[columnName] = {}; |
742 $scope.toggleValuesInSet($scope.allColumnValues[columnName], | 765 $scope.toggleValuesInSet($scope.allColumnValues[columnName], |
743 $scope.showingColumnValues[columnName]); | 766 $scope.showingColumnValues[columnName]); |
744 $scope.updateResults(); | 767 $scope.updateResults(); |
745 } | 768 }; |
746 | 769 |
747 | 770 |
748 // | 771 // |
749 // Operations for sending info back to the server. | 772 // Operations for sending info back to the server. |
750 // | 773 // |
751 | 774 |
752 /** | 775 /** |
753 * Tell the server that the actual results of these particular tests | 776 * Tell the server that the actual results of these particular tests |
754 * are acceptable. | 777 * are acceptable. |
755 * | 778 * |
(...skipping 89 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
845 "finished loading the update results into memory!) and you can " + | 868 "finished loading the update results into memory!) and you can " + |
846 "submit more baselines if you want."); | 869 "submit more baselines if you want."); |
847 // I don't know why, but if I just call reload() here it doesn't work. | 870 // I don't know why, but if I just call reload() here it doesn't work. |
848 // Making a timer call it fixes the problem. | 871 // Making a timer call it fixes the problem. |
849 $timeout(function(){location.reload();}, 1); | 872 $timeout(function(){location.reload();}, 1); |
850 }).error(function(data, status, headers, config) { | 873 }).error(function(data, status, headers, config) { |
851 alert("There was an error submitting your baselines.\n\n" + | 874 alert("There was an error submitting your baselines.\n\n" + |
852 "Please see server-side log for details."); | 875 "Please see server-side log for details."); |
853 $scope.submitPending = false; | 876 $scope.submitPending = false; |
854 }); | 877 }); |
855 } | 878 }; |
856 | 879 |
857 | 880 |
858 // | 881 // |
859 // Operations we use to mimic Set semantics, in such a way that | 882 // Operations we use to mimic Set semantics, in such a way that |
860 // checking for presence within the Set is as fast as possible. | 883 // checking for presence within the Set is as fast as possible. |
861 // But getting a list of all values within the Set is not necessarily | 884 // But getting a list of all values within the Set is not necessarily |
862 // possible. | 885 // possible. |
863 // TODO(epoger): move into a separate .js file? | 886 // TODO(epoger): move into a separate .js file? |
864 // | 887 // |
865 | 888 |
866 /** | 889 /** |
867 * Returns the number of values present within set "set". | 890 * Returns the number of values present within set "set". |
868 * | 891 * |
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 */ | 893 */ |
871 $scope.setSize = function(set) { | 894 $scope.setSize = function(set) { |
872 return Object.keys(set).length; | 895 return Object.keys(set).length; |
873 } | 896 }; |
874 | 897 |
875 /** | 898 /** |
876 * Returns true if value "value" is present within set "set". | 899 * Returns true if value "value" is present within set "set". |
877 * | 900 * |
878 * @param value a value of any type | 901 * @param value a value of any type |
879 * @param set an Object which we use to mimic set semantics | 902 * @param set an Object which we use to mimic set semantics |
880 * (this should make isValueInSet faster than if we used an Array) | 903 * (this should make isValueInSet faster than if we used an Array) |
881 */ | 904 */ |
882 $scope.isValueInSet = function(value, set) { | 905 $scope.isValueInSet = function(value, set) { |
883 return (true == set[value]); | 906 return (true == set[value]); |
884 } | 907 }; |
885 | 908 |
886 /** | 909 /** |
887 * If value "value" is already in set "set", remove it; otherwise, add it. | 910 * If value "value" is already in set "set", remove it; otherwise, add it. |
888 * | 911 * |
889 * @param value a value of any type | 912 * @param value a value of any type |
890 * @param set an Object which we use to mimic set semantics | 913 * @param set an Object which we use to mimic set semantics |
891 */ | 914 */ |
892 $scope.toggleValueInSet = function(value, set) { | 915 $scope.toggleValueInSet = function(value, set) { |
893 if (true == set[value]) { | 916 if (true == set[value]) { |
894 delete set[value]; | 917 delete set[value]; |
895 } else { | 918 } else { |
896 set[value] = true; | 919 set[value] = true; |
897 } | 920 } |
898 } | 921 }; |
899 | 922 |
900 /** | 923 /** |
901 * For each value in valueArray, call toggleValueInSet(value, set). | 924 * For each value in valueArray, call toggleValueInSet(value, set). |
902 * | 925 * |
903 * @param valueArray | 926 * @param valueArray |
904 * @param set | 927 * @param set |
905 */ | 928 */ |
906 $scope.toggleValuesInSet = function(valueArray, set) { | 929 $scope.toggleValuesInSet = function(valueArray, set) { |
907 var arrayLength = valueArray.length; | 930 var arrayLength = valueArray.length; |
908 for (var i = 0; i < arrayLength; i++) { | 931 for (var i = 0; i < arrayLength; i++) { |
909 $scope.toggleValueInSet(valueArray[i], set); | 932 $scope.toggleValueInSet(valueArray[i], set); |
910 } | 933 } |
911 } | 934 }; |
912 | 935 |
913 | 936 |
914 // | 937 // |
915 // Array operations; similar to our Set operations, but operate on a | 938 // Array operations; similar to our Set operations, but operate on a |
916 // Javascript Array so we *can* easily get a list of all values in the Set. | 939 // Javascript Array so we *can* easily get a list of all values in the Set. |
917 // TODO(epoger): move into a separate .js file? | 940 // TODO(epoger): move into a separate .js file? |
918 // | 941 // |
919 | 942 |
920 /** | 943 /** |
921 * Returns true if value "value" is present within array "array". | 944 * Returns true if value "value" is present within array "array". |
922 * | 945 * |
923 * @param value a value of any type | 946 * @param value a value of any type |
924 * @param array a Javascript Array | 947 * @param array a Javascript Array |
925 */ | 948 */ |
926 $scope.isValueInArray = function(value, array) { | 949 $scope.isValueInArray = function(value, array) { |
927 return (-1 != array.indexOf(value)); | 950 return (-1 != array.indexOf(value)); |
928 } | 951 }; |
929 | 952 |
930 /** | 953 /** |
931 * If value "value" is already in array "array", remove it; otherwise, | 954 * If value "value" is already in array "array", remove it; otherwise, |
932 * add it. | 955 * add it. |
933 * | 956 * |
934 * @param value a value of any type | 957 * @param value a value of any type |
935 * @param array a Javascript Array | 958 * @param array a Javascript Array |
936 */ | 959 */ |
937 $scope.toggleValueInArray = function(value, array) { | 960 $scope.toggleValueInArray = function(value, array) { |
938 var i = array.indexOf(value); | 961 var i = array.indexOf(value); |
939 if (-1 == i) { | 962 if (-1 == i) { |
940 array.push(value); | 963 array.push(value); |
941 } else { | 964 } else { |
942 array.splice(i, 1); | 965 array.splice(i, 1); |
943 } | 966 } |
944 } | 967 }; |
945 | 968 |
946 | 969 |
947 // | 970 // |
948 // Miscellaneous utility functions. | 971 // Miscellaneous utility functions. |
949 // TODO(epoger): move into a separate .js file? | 972 // TODO(epoger): move into a separate .js file? |
950 // | 973 // |
951 | 974 |
952 /** | 975 /** |
953 * Returns a single "column slice" of a 2D array. | 976 * Returns a single "column slice" of a 2D array. |
954 * | 977 * |
955 * For example, if array is: | 978 * For example, if array is: |
956 * [[A0, A1], | 979 * [[A0, A1], |
957 * [B0, B1], | 980 * [B0, B1], |
958 * [C0, C1]] | 981 * [C0, C1]] |
959 * and index is 0, this this will return: | 982 * and index is 0, this this will return: |
960 * [A0, B0, C0] | 983 * [A0, B0, C0] |
961 * | 984 * |
962 * @param array a Javascript Array | 985 * @param array a Javascript Array |
963 * @param column (numeric): index within each row array | 986 * @param column (numeric): index within each row array |
964 */ | 987 */ |
965 $scope.columnSliceOf2DArray = function(array, column) { | 988 $scope.columnSliceOf2DArray = function(array, column) { |
966 var slice = []; | 989 var slice = []; |
967 var numRows = array.length; | 990 var numRows = array.length; |
968 for (var row = 0; row < numRows; row++) { | 991 for (var row = 0; row < numRows; row++) { |
969 slice.push(array[row][column]); | 992 slice.push(array[row][column]); |
970 } | 993 } |
971 return slice; | 994 return slice; |
972 } | 995 }; |
973 | 996 |
974 /** | 997 /** |
975 * Returns a human-readable (in local time zone) time string for a | 998 * Returns a human-readable (in local time zone) time string for a |
976 * particular moment in time. | 999 * particular moment in time. |
977 * | 1000 * |
978 * @param secondsPastEpoch (numeric): seconds past epoch in UTC | 1001 * @param secondsPastEpoch (numeric): seconds past epoch in UTC |
979 */ | 1002 */ |
980 $scope.localTimeString = function(secondsPastEpoch) { | 1003 $scope.localTimeString = function(secondsPastEpoch) { |
981 var d = new Date(secondsPastEpoch * 1000); | 1004 var d = new Date(secondsPastEpoch * 1000); |
982 return d.toString(); | 1005 return d.toString(); |
983 } | 1006 }; |
984 | 1007 |
985 /** | 1008 /** |
986 * Returns a hex color string (such as "#aabbcc") for the given RGB values. | 1009 * Returns a hex color string (such as "#aabbcc") for the given RGB values. |
987 * | 1010 * |
988 * @param r (numeric): red channel value, 0-255 | 1011 * @param r (numeric): red channel value, 0-255 |
989 * @param g (numeric): green channel value, 0-255 | 1012 * @param g (numeric): green channel value, 0-255 |
990 * @param b (numeric): blue channel value, 0-255 | 1013 * @param b (numeric): blue channel value, 0-255 |
991 */ | 1014 */ |
992 $scope.hexColorString = function(r, g, b) { | 1015 $scope.hexColorString = function(r, g, b) { |
993 var rString = r.toString(16); | 1016 var rString = r.toString(16); |
994 if (r < 16) { | 1017 if (r < 16) { |
995 rString = "0" + rString; | 1018 rString = "0" + rString; |
996 } | 1019 } |
997 var gString = g.toString(16); | 1020 var gString = g.toString(16); |
998 if (g < 16) { | 1021 if (g < 16) { |
999 gString = "0" + gString; | 1022 gString = "0" + gString; |
1000 } | 1023 } |
1001 var bString = b.toString(16); | 1024 var bString = b.toString(16); |
1002 if (b < 16) { | 1025 if (b < 16) { |
1003 bString = "0" + bString; | 1026 bString = "0" + bString; |
1004 } | 1027 } |
1005 return '#' + rString + gString + bString; | 1028 return '#' + rString + gString + bString; |
1006 } | 1029 }; |
1007 | 1030 |
1008 /** | 1031 /** |
1009 * Returns a hex color string (such as "#aabbcc") for the given brightness. | 1032 * Returns a hex color string (such as "#aabbcc") for the given brightness. |
1010 * | 1033 * |
1011 * @param brightnessString (string): 0-255, 0 is completely black | 1034 * @param brightnessString (string): 0-255, 0 is completely black |
1012 * | 1035 * |
1013 * TODO(epoger): It might be nice to tint the color when it's not completely | 1036 * TODO(epoger): It might be nice to tint the color when it's not completely |
1014 * black or completely white. | 1037 * black or completely white. |
1015 */ | 1038 */ |
1016 $scope.brightnessStringToHexColor = function(brightnessString) { | 1039 $scope.brightnessStringToHexColor = function(brightnessString) { |
1017 var v = parseInt(brightnessString); | 1040 var v = parseInt(brightnessString); |
1018 return $scope.hexColorString(v, v, v); | 1041 return $scope.hexColorString(v, v, v); |
1019 } | 1042 }; |
1020 | 1043 |
1021 /** | 1044 /** |
1022 * Returns the last path component of image diff URL for a given ImagePair. | 1045 * Returns the last path component of image diff URL for a given ImagePair. |
1023 * | 1046 * |
1024 * Depending on which diff this is (whitediffs, pixeldiffs, etc.) this | 1047 * Depending on which diff this is (whitediffs, pixeldiffs, etc.) this |
1025 * will be relative to different base URLs. | 1048 * will be relative to different base URLs. |
1026 * | 1049 * |
1027 * We must keep this function in sync with _get_difference_locator() in | 1050 * We must keep this function in sync with _get_difference_locator() in |
1028 * ../imagediffdb.py | 1051 * ../imagediffdb.py |
1029 * | 1052 * |
1030 * @param imagePair: ImagePair to generate image diff URL for | 1053 * @param imagePair: ImagePair to generate image diff URL for |
1031 */ | 1054 */ |
1032 $scope.getImageDiffRelativeUrl = function(imagePair) { | 1055 $scope.getImageDiffRelativeUrl = function(imagePair) { |
1033 var before = | 1056 var before = |
1034 imagePair[constants.KEY__IMAGEPAIRS__IMAGE_A_URL] + "-vs-" + | 1057 imagePair[constants.KEY__IMAGEPAIRS__IMAGE_A_URL] + "-vs-" + |
1035 imagePair[constants.KEY__IMAGEPAIRS__IMAGE_B_URL]; | 1058 imagePair[constants.KEY__IMAGEPAIRS__IMAGE_B_URL]; |
1036 return before.replace(/[^\w\-]/g, "_") + ".png"; | 1059 return before.replace(/[^\w\-]/g, "_") + ".png"; |
1037 } | 1060 }; |
1038 | 1061 |
1039 } | 1062 } |
1040 ); | 1063 ); |
OLD | NEW |