| Index: gm/rebaseline_server/static/loader.js
|
| diff --git a/gm/rebaseline_server/static/loader.js b/gm/rebaseline_server/static/loader.js
|
| index 9384196fb12fa7a42785b4bc0b34b3303d625164..19bc2378a0cbfd16b30d98bdf6a46151568aa8b4 100644
|
| --- a/gm/rebaseline_server/static/loader.js
|
| +++ b/gm/rebaseline_server/static/loader.js
|
| @@ -30,24 +30,29 @@ Loader.directive(
|
| Loader.filter(
|
| 'removeHiddenImagePairs',
|
| function(constants) {
|
| - return function(unfilteredImagePairs, showingColumnValues,
|
| - builderSubstring, testSubstring, viewingTab) {
|
| + return function(unfilteredImagePairs, filterableColumnNames, showingColumnValues,
|
| + viewingTab) {
|
| var filteredImagePairs = [];
|
| for (var i = 0; i < unfilteredImagePairs.length; i++) {
|
| var imagePair = unfilteredImagePairs[i];
|
| var extraColumnValues = imagePair[constants.KEY__IMAGEPAIRS__EXTRACOLUMNS];
|
| - // For performance, we examine the "set" objects directly rather
|
| - // than calling $scope.isValueInSet().
|
| - // Besides, I don't think we have access to $scope in here...
|
| - if (showingColumnValues[constants.KEY__EXTRACOLUMNS__RESULT_TYPE]
|
| - [extraColumnValues[constants.KEY__EXTRACOLUMNS__RESULT_TYPE]] &&
|
| - showingColumnValues[constants.KEY__EXTRACOLUMNS__CONFIG]
|
| - [extraColumnValues[constants.KEY__EXTRACOLUMNS__CONFIG]] &&
|
| - !(-1 == extraColumnValues[constants.KEY__EXTRACOLUMNS__BUILDER]
|
| - .indexOf(builderSubstring)) &&
|
| - !(-1 == extraColumnValues[constants.KEY__EXTRACOLUMNS__TEST]
|
| - .indexOf(testSubstring)) &&
|
| - (viewingTab == imagePair.tab)) {
|
| + var allColumnValuesAreVisible = true;
|
| + // Loop over all columns, and if any of them contain values not found in
|
| + // showingColumnValues[columnName], don't include this imagePair.
|
| + //
|
| + // We use this same filtering mechanism regardless of whether each column
|
| + // has USE_FREEFORM_FILTER set or not; if that flag is set, then we will
|
| + // have already used the freeform text entry block to populate
|
| + // showingColumnValues[columnName].
|
| + for (var j = 0; j < filterableColumnNames.length; j++) {
|
| + var columnName = filterableColumnNames[j];
|
| + var columnValue = extraColumnValues[columnName];
|
| + if (!showingColumnValues[columnName][columnValue]) {
|
| + allColumnValuesAreVisible = false;
|
| + break;
|
| + }
|
| + }
|
| + if (allColumnValuesAreVisible && (viewingTab == imagePair.tab)) {
|
| filteredImagePairs.push(imagePair);
|
| }
|
| }
|
| @@ -159,6 +164,7 @@ Loader.controller(
|
|
|
| $scope.header = dataHeader;
|
| $scope.extraColumnHeaders = data[constants.KEY__ROOT__EXTRACOLUMNHEADERS];
|
| + $scope.orderedColumnNames = data[constants.KEY__ROOT__EXTRACOLUMNORDER];
|
| $scope.imagePairs = data[constants.KEY__ROOT__IMAGEPAIRS];
|
| $scope.imageSets = data[constants.KEY__ROOT__IMAGESETS];
|
| $scope.sortColumnSubdict = constants.KEY__IMAGEPAIRS__DIFFERENCES;
|
| @@ -200,41 +206,69 @@ Loader.controller(
|
| // Arrays within which the user can toggle individual elements.
|
| $scope.selectedImagePairs = [];
|
|
|
| + // Set up filters.
|
| + //
|
| + // filterableColumnNames is a list of all column names we can filter on.
|
| // allColumnValues[columnName] is a list of all known values
|
| - // for this column.
|
| + // for a given column.
|
| // showingColumnValues[columnName] is a set indicating which values
|
| - // in this column would cause us to show a row, rather than hiding it.
|
| + // in a given column would cause us to show a row, rather than hiding it.
|
| + //
|
| + // columnStringMatch[columnName] is a string used as a pattern to generate
|
| + // showingColumnValues[columnName] for columns we filter using free-form text.
|
| + // It is ignored for any columns with USE_FREEFORM_FILTER == false.
|
| + $scope.filterableColumnNames = [];
|
| $scope.allColumnValues = {};
|
| $scope.showingColumnValues = {};
|
| + $scope.columnStringMatch = {};
|
|
|
| - // set allColumnValues/showingColumnValues for RESULT_TYPE;
|
| + angular.forEach(
|
| + Object.keys($scope.extraColumnHeaders),
|
| + function(columnName) {
|
| + var columnHeader = $scope.extraColumnHeaders[columnName];
|
| + if (columnHeader[constants.KEY__EXTRACOLUMNHEADERS__IS_FILTERABLE]) {
|
| + $scope.filterableColumnNames.push(columnName);
|
| + $scope.allColumnValues[columnName] = $scope.columnSliceOf2DArray(
|
| + columnHeader[constants.KEY__EXTRACOLUMNHEADERS__VALUES_AND_COUNTS], 0);
|
| + $scope.showingColumnValues[columnName] = {};
|
| + $scope.toggleValuesInSet($scope.allColumnValues[columnName],
|
| + $scope.showingColumnValues[columnName]);
|
| + $scope.columnStringMatch[columnName] = "";
|
| + }
|
| + }
|
| + );
|
| +
|
| + // TODO(epoger): Special handling for RESULT_TYPE column:
|
| // by default, show only KEY__RESULT_TYPE__FAILED results
|
| - $scope.allColumnValues[constants.KEY__EXTRACOLUMNS__RESULT_TYPE] =
|
| - $scope.columnSliceOf2DArray(
|
| - $scope.extraColumnHeaders[constants.KEY__EXTRACOLUMNS__RESULT_TYPE]
|
| - [constants.KEY__EXTRACOLUMNHEADERS__VALUES_AND_COUNTS],
|
| - 0);
|
| $scope.showingColumnValues[constants.KEY__EXTRACOLUMNS__RESULT_TYPE] = {};
|
| $scope.showingColumnValues[constants.KEY__EXTRACOLUMNS__RESULT_TYPE][
|
| constants.KEY__RESULT_TYPE__FAILED] = true;
|
|
|
| - // set allColumnValues/showingColumnValues for CONFIG;
|
| - // by default, show results for all configs
|
| - $scope.allColumnValues[constants.KEY__EXTRACOLUMNS__CONFIG] =
|
| - $scope.columnSliceOf2DArray(
|
| - $scope.extraColumnHeaders[constants.KEY__EXTRACOLUMNS__CONFIG]
|
| - [constants.KEY__EXTRACOLUMNHEADERS__VALUES_AND_COUNTS],
|
| - 0);
|
| - $scope.showingColumnValues[constants.KEY__EXTRACOLUMNS__CONFIG] = {};
|
| - $scope.toggleValuesInSet($scope.allColumnValues[constants.KEY__EXTRACOLUMNS__CONFIG],
|
| - $scope.showingColumnValues[constants.KEY__EXTRACOLUMNS__CONFIG]);
|
| -
|
| - // Associative array of partial string matches per category.
|
| - // TODO(epoger): Rename as columnValueMatch to be more consistent
|
| - // with allColumnValues/showingColumnValues ?
|
| - $scope.categoryValueMatch = {};
|
| - $scope.categoryValueMatch[constants.KEY__EXTRACOLUMNS__BUILDER] = "";
|
| - $scope.categoryValueMatch[constants.KEY__EXTRACOLUMNS__TEST] = "";
|
| + // Set up mapping for URL parameters.
|
| + // parameter name -> copier object to load/save parameter value
|
| + $scope.queryParameters.map = {
|
| + 'resultsToLoad': $scope.queryParameters.copiers.simple,
|
| + 'displayLimitPending': $scope.queryParameters.copiers.simple,
|
| + 'showThumbnailsPending': $scope.queryParameters.copiers.simple,
|
| + 'mergeIdenticalRowsPending': $scope.queryParameters.copiers.simple,
|
| + 'imageSizePending': $scope.queryParameters.copiers.simple,
|
| + 'sortColumnSubdict': $scope.queryParameters.copiers.simple,
|
| + 'sortColumnKey': $scope.queryParameters.copiers.simple,
|
| + };
|
| + // Some parameters are handled differently based on whether they USE_FREEFORM_FILTER.
|
| + angular.forEach(
|
| + $scope.filterableColumnNames,
|
| + function(columnName) {
|
| + if ($scope.extraColumnHeaders[columnName]
|
| + [constants.KEY__EXTRACOLUMNHEADERS__USE_FREEFORM_FILTER]) {
|
| + $scope.queryParameters.map[columnName] =
|
| + $scope.queryParameters.copiers.columnStringMatch;
|
| + } else {
|
| + $scope.queryParameters.map[columnName] =
|
| + $scope.queryParameters.copiers.showingColumnValuesSet;
|
| + }
|
| + }
|
| + );
|
|
|
| // If any defaults were overridden in the URL, get them now.
|
| $scope.queryParameters.load();
|
| @@ -391,15 +425,15 @@ Loader.controller(
|
| }
|
| },
|
|
|
| - 'categoryValueMatch': {
|
| + 'columnStringMatch': {
|
| 'load': function(nameValuePairs, name) {
|
| var value = nameValuePairs[name];
|
| if (value) {
|
| - $scope.categoryValueMatch[name] = value;
|
| + $scope.columnStringMatch[name] = value;
|
| }
|
| },
|
| 'save': function(nameValuePairs, name) {
|
| - nameValuePairs[name] = $scope.categoryValueMatch[name];
|
| + nameValuePairs[name] = $scope.columnStringMatch[name];
|
| }
|
| },
|
|
|
| @@ -419,25 +453,6 @@ Loader.controller(
|
|
|
| };
|
|
|
| - // parameter name -> copier objects to load/save parameter value
|
| - $scope.queryParameters.map = {
|
| - 'resultsToLoad': $scope.queryParameters.copiers.simple,
|
| - 'displayLimitPending': $scope.queryParameters.copiers.simple,
|
| - 'showThumbnailsPending': $scope.queryParameters.copiers.simple,
|
| - 'mergeIdenticalRowsPending': $scope.queryParameters.copiers.simple,
|
| - 'imageSizePending': $scope.queryParameters.copiers.simple,
|
| - 'sortColumnSubdict': $scope.queryParameters.copiers.simple,
|
| - 'sortColumnKey': $scope.queryParameters.copiers.simple,
|
| - };
|
| - $scope.queryParameters.map[constants.KEY__EXTRACOLUMNS__RESULT_TYPE] =
|
| - $scope.queryParameters.copiers.showingColumnValuesSet;
|
| - $scope.queryParameters.map[constants.KEY__EXTRACOLUMNS__BUILDER] =
|
| - $scope.queryParameters.copiers.categoryValueMatch;
|
| - $scope.queryParameters.map[constants.KEY__EXTRACOLUMNS__TEST] =
|
| - $scope.queryParameters.copiers.categoryValueMatch;
|
| - $scope.queryParameters.map[constants.KEY__EXTRACOLUMNS__CONFIG] =
|
| - $scope.queryParameters.copiers.showingColumnValuesSet;
|
| -
|
| // Loads all parameters into $scope from the URL query string;
|
| // any which are not found within the URL will keep their current value.
|
| $scope.queryParameters.load = function() {
|
| @@ -550,6 +565,30 @@ Loader.controller(
|
| $log.debug("renderStartTime: " + $scope.renderStartTime);
|
| $scope.displayLimit = $scope.displayLimitPending;
|
| $scope.mergeIdenticalRows = $scope.mergeIdenticalRowsPending;
|
| +
|
| + // For each USE_FREEFORM_FILTER column, populate showingColumnValues.
|
| + // This is more efficient than applying the freeform filter within the
|
| + // tight loop in removeHiddenImagePairs.
|
| + angular.forEach(
|
| + $scope.filterableColumnNames,
|
| + function(columnName) {
|
| + var columnHeader = $scope.extraColumnHeaders[columnName];
|
| + if (columnHeader[constants.KEY__EXTRACOLUMNHEADERS__USE_FREEFORM_FILTER]) {
|
| + var columnStringMatch = $scope.columnStringMatch[columnName];
|
| + var showingColumnValues = {};
|
| + angular.forEach(
|
| + $scope.allColumnValues[columnName],
|
| + function(columnValue) {
|
| + if (-1 != columnValue.indexOf(columnStringMatch)) {
|
| + showingColumnValues[columnValue] = true;
|
| + }
|
| + }
|
| + );
|
| + $scope.showingColumnValues[columnName] = showingColumnValues;
|
| + }
|
| + }
|
| + );
|
| +
|
| // TODO(epoger): Every time we apply a filter, AngularJS creates
|
| // another copy of the array. Is there a way we can filter out
|
| // the imagePairs as they are displayed, rather than storing multiple
|
| @@ -569,9 +608,8 @@ Loader.controller(
|
| $filter("orderBy")(
|
| $filter("removeHiddenImagePairs")(
|
| $scope.imagePairs,
|
| + $scope.filterableColumnNames,
|
| $scope.showingColumnValues,
|
| - $scope.categoryValueMatch[constants.KEY__EXTRACOLUMNS__BUILDER],
|
| - $scope.categoryValueMatch[constants.KEY__EXTRACOLUMNS__TEST],
|
| $scope.viewingTab
|
| ),
|
| [$scope.getSortColumnValue, $scope.getSecondOrderSortValue],
|
| @@ -652,36 +690,40 @@ Loader.controller(
|
| }
|
|
|
| /**
|
| - * Set $scope.categoryValueMatch[name] = value, and update results.
|
| + * Set $scope.columnStringMatch[name] = value, and update results.
|
| *
|
| * @param name
|
| * @param value
|
| */
|
| - $scope.setCategoryValueMatch = function(name, value) {
|
| - $scope.categoryValueMatch[name] = value;
|
| + $scope.setColumnStringMatch = function(name, value) {
|
| + $scope.columnStringMatch[name] = value;
|
| $scope.updateResults();
|
| }
|
|
|
| /**
|
| - * Update $scope.showingColumnValues[columnName] so that ONLY entries with
|
| - * this columnValue are showing, and update the visible results.
|
| + * Update $scope.showingColumnValues[columnName] and $scope.columnStringMatch[columnName]
|
| + * so that ONLY entries with this columnValue are showing, and update the visible results.
|
| + * (We update both of those, so we cover both freeform and checkbox filtered columns.)
|
| *
|
| * @param columnName
|
| * @param columnValue
|
| */
|
| $scope.showOnlyColumnValue = function(columnName, columnValue) {
|
| + $scope.columnStringMatch[columnName] = columnValue;
|
| $scope.showingColumnValues[columnName] = {};
|
| $scope.toggleValueInSet(columnValue, $scope.showingColumnValues[columnName]);
|
| $scope.updateResults();
|
| }
|
|
|
| /**
|
| - * Update $scope.showingColumnValues[columnName] so that ALL entries are
|
| - * showing, and update the visible results.
|
| + * Update $scope.showingColumnValues[columnName] and $scope.columnStringMatch[columnName]
|
| + * so that ALL entries are showing, and update the visible results.
|
| + * (We update both of those, so we cover both freeform and checkbox filtered columns.)
|
| *
|
| * @param columnName
|
| */
|
| $scope.showAllColumnValues = function(columnName) {
|
| + $scope.columnStringMatch[columnName] = "";
|
| $scope.showingColumnValues[columnName] = {};
|
| $scope.toggleValuesInSet($scope.allColumnValues[columnName],
|
| $scope.showingColumnValues[columnName]);
|
|
|