diff options
Diffstat (limited to 'gm/rebaseline_server/static/live-view.html')
-rw-r--r-- | gm/rebaseline_server/static/live-view.html | 446 |
1 files changed, 446 insertions, 0 deletions
diff --git a/gm/rebaseline_server/static/live-view.html b/gm/rebaseline_server/static/live-view.html new file mode 100644 index 0000000000..1662adf89c --- /dev/null +++ b/gm/rebaseline_server/static/live-view.html @@ -0,0 +1,446 @@ +<!DOCTYPE html> + +<html ng-app="Loader" ng-controller="Loader.Controller"> + +<head> + <title ng-bind="windowTitle"></title> + <script src="//ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script> + <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.20/angular.js"></script> + <script src="constants.js"></script> + <script src="live-loader.js"></script> + <script src="utils.js"></script> + + <link rel="stylesheet" href="view.css"> +</head> + +<body> + <h2> + Instructions, roadmap, etc. are at + <a href="http://tinyurl.com/SkiaRebaselineServer"> + http://tinyurl.com/SkiaRebaselineServer + </a> + </h2> + + <em ng-show="!readyToDisplay"> + Loading results of query: + <ul> + <li>setA: "{{setASection}}" within {{setADir}}</li> + <li>setB: "{{setBSection}}" within {{setBDir}}</li> + </ul> + <br> + {{loadingMessage}} + </em> + + <div ng-show="readyToDisplay"> + + <div class="warning-div" + ng-show="urlSchemaVersionLoaded != constants.URL_VALUE__SCHEMA_VERSION__CURRENT"> + WARNING! The URL you loaded used schema version {{urlSchemaVersionLoaded}}, rather than + the most recent version {{constants.URL_VALUE__SCHEMA_VERSION__CURRENT}}. It has been + converted to the most recent version on a best-effort basis; you may wish to double-check + which records are displayed. + </div> + + <div ng-show="header[constants.KEY__HEADER__TIME_UPDATED]"> + setA: "{{header[constants.KEY__HEADER__SET_A_DESCRIPTIONS][constants.KEY__SET_DESCRIPTIONS__SECTION]}}" + within {{header[constants.KEY__HEADER__SET_A_DESCRIPTIONS][constants.KEY__SET_DESCRIPTIONS__DIR]}} + <span ng-show="header[constants.KEY__HEADER__SET_A_DESCRIPTIONS][constants.KEY__SET_DESCRIPTIONS__REPO_REVISION]">at <a href="https://skia.googlesource.com/skia/+/{{header[constants.KEY__HEADER__SET_A_DESCRIPTIONS][constants.KEY__SET_DESCRIPTIONS__REPO_REVISION]}}">rev {{header[constants.KEY__HEADER__SET_A_DESCRIPTIONS][constants.KEY__SET_DESCRIPTIONS__REPO_REVISION]}}</a></span> + <br> + setB: "{{header[constants.KEY__HEADER__SET_B_DESCRIPTIONS][constants.KEY__SET_DESCRIPTIONS__SECTION]}}" + within {{header[constants.KEY__HEADER__SET_B_DESCRIPTIONS][constants.KEY__SET_DESCRIPTIONS__DIR]}} + <span ng-show="header[constants.KEY__HEADER__SET_B_DESCRIPTIONS][constants.KEY__SET_DESCRIPTIONS__REPO_REVISION]">at <a href="https://skia.googlesource.com/skia/+/{{header[constants.KEY__HEADER__SET_B_DESCRIPTIONS][constants.KEY__SET_DESCRIPTIONS__REPO_REVISION]}}">rev {{header[constants.KEY__HEADER__SET_B_DESCRIPTIONS][constants.KEY__SET_DESCRIPTIONS__REPO_REVISION]}}</a></span> + <br> + <a href="{{liveQueryUrl}}">latest raw JSON diffs between these two sets</a><br> + These results current as of + {{localTimeString(header[constants.KEY__HEADER__TIME_UPDATED])}} + </div> + + <div class="tab-wrapper"><!-- tabs --> + <div class="tab-spacer" ng-repeat="tab in tabs"> + <div class="tab tab-{{tab == viewingTab}}" + ng-click="setViewingTab(tab)"> + {{tab}} ({{numResultsPerTab[tab]}}) + </div> + <div class="tab-spacer"> + + </div> + </div> + </div><!-- tabs --> + + <div class="tab-main"><!-- main display area of selected tab --> + + <br> + <!-- We only show the filters/settings table on the Unfiled tab. --> + <table ng-show="viewingTab == defaultTab" border="1"> + <tr> + <th colspan="4"> + Filters + </th> + <th> + Settings + </th> + </tr> + <tr valign="top"> + + <!-- filters --> + <td ng-repeat="columnName in orderedColumnNames"> + + <!-- Only display filterable columns here... --> + <div ng-if="extraColumnHeaders[columnName][constants.KEY__EXTRACOLUMNHEADERS__IS_FILTERABLE]"> + {{extraColumnHeaders[columnName][constants.KEY__EXTRACOLUMNHEADERS__HEADER_TEXT]}}<br> + + <!-- If we filter this column using free-form text match... --> + <div ng-if="extraColumnHeaders[columnName][constants.KEY__EXTRACOLUMNHEADERS__USE_FREEFORM_FILTER]"> + <input type="text" + ng-model="columnStringMatch[columnName]" + ng-change="setUpdatesPending(true)"/> + <br> + <button ng-click="setColumnStringMatch(columnName, '')" + ng-disabled="('' == columnStringMatch[columnName])"> + clear (show all) + </button> + </div> + + <!-- If we filter this column using checkboxes... --> + <div ng-if="!extraColumnHeaders[columnName][constants.KEY__EXTRACOLUMNHEADERS__USE_FREEFORM_FILTER]"> + <label ng-repeat="valueAndCount in extraColumnHeaders[columnName][constants.KEY__EXTRACOLUMNHEADERS__VALUES_AND_COUNTS]"> + <input type="checkbox" + name="resultTypes" + value="{{valueAndCount[0]}}" + ng-checked="isValueInSet(valueAndCount[0], showingColumnValues[columnName])" + ng-click="toggleValueInSet(valueAndCount[0], showingColumnValues[columnName]); setUpdatesPending(true)"> + {{valueAndCount[0]}} ({{valueAndCount[1]}})<br> + </label> + <button ng-click="showingColumnValues[columnName] = {}; toggleValuesInSet(allColumnValues[columnName], showingColumnValues[columnName]); updateResults()" + ng-disabled="!readyToDisplay || allColumnValues[columnName].length == setSize(showingColumnValues[columnName])"> + all + </button> + <button ng-click="showingColumnValues[columnName] = {}; updateResults()" + ng-disabled="!readyToDisplay || 0 == setSize(showingColumnValues[columnName])"> + none + </button> + <button ng-click="toggleValuesInSet(allColumnValues[columnName], showingColumnValues[columnName]); updateResults()"> + toggle + </button> + </div> + + </div> + </td> + + <!-- settings --> + <td><table> + <tr><td> + <input type="checkbox" ng-model="showThumbnailsPending" + ng-init="showThumbnailsPending = true" + ng-change="areUpdatesPending = true"/> + Show thumbnails + </td></tr> + <tr><td> + <input type="checkbox" ng-model="mergeIdenticalRowsPending" + ng-init="mergeIdenticalRowsPending = true" + ng-change="areUpdatesPending = true"/> + Merge identical rows + </td></tr> + <tr><td> + Image width + <input type="text" ng-model="imageSizePending" + ng-init="imageSizePending=100" + ng-change="areUpdatesPending = true" + maxlength="4"/> + </td></tr> + <tr><td> + Max records to display + <input type="text" ng-model="displayLimitPending" + ng-init="displayLimitPending=50" + ng-change="areUpdatesPending = true" + maxlength="4"/> + </td></tr> + <tr><td> + <button class="update-results-button" + ng-click="updateResults()" + ng-disabled="!areUpdatesPending"> + Update Results + </button> + </td></tr> + </tr></table></td> + </tr> + </table> + + <p> + + <!-- Submission UI that we only show in the Pending Approval tab. --> + <div ng-show="'Pending Approval' == viewingTab"> + <div style="display:inline-block"> + <button style="font-size:20px" + ng-click="submitApprovals(filteredImagePairs)" + ng-disabled="submitPending || (filteredImagePairs.length == 0)"> + Get a patchfile to update these {{filteredImagePairs.length}} expectations + </button> + </div> + <div style="display:inline-block"> + <div style="font-size:20px" + ng-show="submitPending"> + Submitting, please wait... + </div> + </div> + <div> + Advanced settings... + <input type="checkbox" ng-model="showSubmitAdvancedSettings"> + show + <ul ng-show="showSubmitAdvancedSettings"> + <li ng-repeat="setting in [constants.KEY__EXPECTATIONS__REVIEWED, constants.KEY__EXPECTATIONS__IGNOREFAILURE]"> + {{setting}} + <input type="checkbox" ng-model="submitAdvancedSettings[setting]"> + </li> + <li ng-repeat="setting in ['bug']"> + {{setting}} + <input type="text" ng-model="submitAdvancedSettings[setting]"> + </li> + </ul> + </div> + <div ng-show="diffResults"> + <p> + Here is the patch to apply to your local checkout: + <br> + <textarea rows="8" cols="50">{{diffResults}}</textarea> + <br> + <a download="patch.txt" ng-href="{{diffResultsBlobUrl}}"> + Click here to download that patch as a text file. + </a> + </div> + </div> + + <p> + + <table border="0"><tr><td> <!-- table holding results header + results table --> + <table border="0" width="100%"> <!-- results header --> + <tr> + <td> + Found {{filteredImagePairs.length}} matches; + <span ng-show="filteredImagePairs.length > limitedImagePairs.length"> + displaying the first {{limitedImagePairs.length}}. + </span> + <span ng-show="filteredImagePairs.length <= limitedImagePairs.length"> + displaying them all. + </span> + <span ng-show="renderEndTime > renderStartTime"> + Rendered in {{(renderEndTime - renderStartTime).toFixed(0)}} ms. + </span> + <br> + (click on the column header radio buttons to re-sort by that column) + </td> + <td align="right"> + <div> + all tests shown: + <button ng-click="selectAllImagePairs()"> + select + </button> + <button ng-click="clearAllImagePairs()"> + clear + </button> + <button ng-click="toggleAllImagePairs()"> + toggle + </button> + </div> + <div ng-repeat="otherTab in tabs"> + <button ng-click="moveSelectedImagePairsToTab(otherTab)" + ng-disabled="selectedImagePairs.length == 0" + ng-show="otherTab != viewingTab"> + move {{selectedImagePairs.length}} selected tests to {{otherTab}} tab + </button> + </div> + </td> + </tr> + </table> <!-- results header --> + </td></tr><tr><td> + <table border="1" ng-app="diff_viewer"> <!-- results --> + <tr> + <!-- Most column headers are displayed in a common fashion... --> + <th ng-repeat="columnName in orderedColumnNames"> + <a ng-class="'sort-' + sortedByColumnsCls(columnName)" + ng-click="sortResultsBy(constants.KEY__IMAGEPAIRS__EXTRACOLUMNS, columnName)" + href="" + class="sortable-header"> + {{extraColumnHeaders[columnName][constants.KEY__EXTRACOLUMNHEADERS__HEADER_TEXT]}} + </a> + </th> + <!-- ... but there are a few columns where we display things differently. --> + <th> + <a ng-class="'sort-' + sortedByColumnsCls(constants.KEY__EXPECTATIONS__BUGS)" + ng-click="sortResultsBy(constants.KEY__IMAGEPAIRS__EXPECTATIONS, constants.KEY__EXPECTATIONS__BUGS)" + href="" + class="sortable-header"> + bugs + </a> + </th> + <th width="{{imageSize}}"> + <a ng-class="'sort-' + sortedByColumnsCls(constants.KEY__IMAGEPAIRS__IMAGE_A_URL)" + ng-click="sortResultsBy('none', constants.KEY__IMAGEPAIRS__IMAGE_A_URL)" + href="" + title="setA: '{{header[constants.KEY__HEADER__SET_A_DESCRIPTIONS][constants.KEY__SET_DESCRIPTIONS__SECTION]}}' within {{header[constants.KEY__HEADER__SET_A_DESCRIPTIONS][constants.KEY__SET_DESCRIPTIONS__DIR]}}" + class="sortable-header"> + <span ng-show="'Pending Approval' != viewingTab"> + {{imageSets[constants.KEY__IMAGESETS__SET__IMAGE_A][constants.KEY__IMAGESETS__FIELD__DESCRIPTION]}} + </span> + <span ng-show="'Pending Approval' == viewingTab"> + old expectations + </span> + </a> + </th> + <th width="{{imageSize}}"> + <a ng-class="'sort-' + sortedByColumnsCls(constants.KEY__IMAGEPAIRS__IMAGE_B_URL)" + ng-click="sortResultsBy('none', constants.KEY__IMAGEPAIRS__IMAGE_B_URL)" + href="" + title="setB: '{{header[constants.KEY__HEADER__SET_B_DESCRIPTIONS][constants.KEY__SET_DESCRIPTIONS__SECTION]}}' within {{header[constants.KEY__HEADER__SET_B_DESCRIPTIONS][constants.KEY__SET_DESCRIPTIONS__DIR]}}" + class="sortable-header"> + <span ng-show="'Pending Approval' != viewingTab"> + {{imageSets[constants.KEY__IMAGESETS__SET__IMAGE_B][constants.KEY__IMAGESETS__FIELD__DESCRIPTION]}} + </span> + <span ng-show="'Pending Approval' == viewingTab"> + new expectations + </span> + </a> + </th> + <th width="{{imageSize}}"> + <a ng-class="'sort-' + sortedByColumnsCls(constants.KEY__DIFFERENCES__PERCENT_DIFF_PIXELS)" + ng-click="sortResultsBy(constants.KEY__IMAGEPAIRS__DIFFERENCES, constants.KEY__DIFFERENCES__PERCENT_DIFF_PIXELS)" + href="" + class="sortable-header"> + differing pixels in white + </a> + </th> + <th width="{{imageSize}}"> + <a ng-class="'sort-' + sortedByColumnsCls(constants.KEY__DIFFERENCES__PERCEPTUAL_DIFF)" + ng-click="sortResultsBy(constants.KEY__IMAGEPAIRS__DIFFERENCES, constants.KEY__DIFFERENCES__PERCEPTUAL_DIFF)" + href="" + class="sortable-header"> + perceptual difference + </a> + <br> + <input type="range" ng-model="pixelDiffBgColorBrightness" + ng-init="pixelDiffBgColorBrightness=64; pixelDiffBgColor=brightnessStringToHexColor(pixelDiffBgColorBrightness)" + ng-change="pixelDiffBgColor=brightnessStringToHexColor(pixelDiffBgColorBrightness)" + title="image background brightness" + min="0" max="255"/> + </th> + <th> + <!-- imagepair-selection checkbox column --> + </th> + </tr> + + <tr ng-repeat="imagePair in limitedImagePairs" valign="top" + ng-class-odd="'results-odd'" ng-class-even="'results-even'" + results-updated-callback-directive> + + <td ng-repeat="columnName in orderedColumnNames"> + {{imagePair[constants.KEY__IMAGEPAIRS__EXTRACOLUMNS][columnName]}} + <br> + <button class="show-only-button" + ng-show="viewingTab == defaultTab" + ng-disabled="1 == setSize(showingColumnValues[columnName])" + ng-click="showOnlyColumnValue(columnName, imagePair[constants.KEY__IMAGEPAIRS__EXTRACOLUMNS][columnName])" + title="show only results of {{extraColumnHeaders[columnName][constants.KEY__EXTRACOLUMNHEADERS__HEADER_TEXT]}} {{imagePair[constants.KEY__IMAGEPAIRS__EXTRACOLUMNS][columnName]}}"> + show only + </button> + <br> + <button class="show-all-button" + ng-show="viewingTab == defaultTab" + ng-disabled="allColumnValues[columnName].length == setSize(showingColumnValues[columnName])" + ng-click="showAllColumnValues(columnName)" + title="show results of all {{extraColumnHeaders[columnName][constants.KEY__EXTRACOLUMNHEADERS__HEADER_TEXT]}}s"> + show all + </button> + </td> + + <!-- bugs --> + <td> + <a ng-repeat="bug in imagePair[constants.KEY__IMAGEPAIRS__EXPECTATIONS][constants.KEY__EXPECTATIONS__BUGS]" + href="https://code.google.com/p/skia/issues/detail?id={{bug}}" + target="_blank"> + {{bug}} + </a> + </td> + + <!-- image A --> + <td width="{{imageSize}}" ng-if="imagePair[constants.KEY__IMAGEPAIRS__ROWSPAN] > 0" rowspan="{{imagePair[constants.KEY__IMAGEPAIRS__ROWSPAN]}}"> + <div ng-if="imagePair[constants.KEY__IMAGEPAIRS__IMAGE_A_URL] != null"> + <a href="{{imageSets[constants.KEY__IMAGESETS__SET__IMAGE_A][constants.KEY__IMAGESETS__FIELD__BASE_URL]}}/{{imagePair[constants.KEY__IMAGEPAIRS__IMAGE_A_URL]}}" target="_blank">View Image</a><br/> + <img ng-if="showThumbnails" + width="{{imageSize}}" + ng-src="{{imageSets[constants.KEY__IMAGESETS__SET__IMAGE_A][constants.KEY__IMAGESETS__FIELD__BASE_URL]}}/{{imagePair[constants.KEY__IMAGEPAIRS__IMAGE_A_URL]}}" /> + </div> + <div ng-show="imagePair[constants.KEY__IMAGEPAIRS__IMAGE_A_URL] == null" + style="text-align:center"> + –none– + </div> + </td> + + <!-- image B --> + <td width="{{imageSize}}" ng-if="imagePair[constants.KEY__IMAGEPAIRS__ROWSPAN] > 0" rowspan="{{imagePair[constants.KEY__IMAGEPAIRS__ROWSPAN]}}"> + <div ng-if="imagePair[constants.KEY__IMAGEPAIRS__IMAGE_B_URL] != null"> + <a href="{{imageSets[constants.KEY__IMAGESETS__SET__IMAGE_B][constants.KEY__IMAGESETS__FIELD__BASE_URL]}}/{{imagePair[constants.KEY__IMAGEPAIRS__IMAGE_B_URL]}}" target="_blank">View Image</a><br/> + <img ng-if="showThumbnails" + width="{{imageSize}}" + ng-src="{{imageSets[constants.KEY__IMAGESETS__SET__IMAGE_B][constants.KEY__IMAGESETS__FIELD__BASE_URL]}}/{{imagePair[constants.KEY__IMAGEPAIRS__IMAGE_B_URL]}}" /> + </div> + <div ng-show="imagePair[constants.KEY__IMAGEPAIRS__IMAGE_B_URL] == null" + style="text-align:center"> + –none– + </div> + </td> + + <!-- whitediffs: every differing pixel shown in white --> + <td width="{{imageSize}}" ng-if="imagePair[constants.KEY__IMAGEPAIRS__ROWSPAN] > 0" rowspan="{{imagePair[constants.KEY__IMAGEPAIRS__ROWSPAN]}}"> + <div ng-if="imagePair[constants.KEY__IMAGEPAIRS__IS_DIFFERENT]" + title="{{imagePair[constants.KEY__IMAGEPAIRS__DIFFERENCES][constants.KEY__DIFFERENCES__NUM_DIFF_PIXELS] | number:0}} of {{(100 * imagePair[constants.KEY__IMAGEPAIRS__DIFFERENCES][constants.KEY__DIFFERENCES__NUM_DIFF_PIXELS] / imagePair[constants.KEY__IMAGEPAIRS__DIFFERENCES][constants.KEY__DIFFERENCES__PERCENT_DIFF_PIXELS]) | number:0}} pixels ({{imagePair[constants.KEY__IMAGEPAIRS__DIFFERENCES][constants.KEY__DIFFERENCES__PERCENT_DIFF_PIXELS].toFixed(4)}}%) differ from expectation."> + + <a href="{{imageSets[constants.KEY__IMAGESETS__SET__WHITEDIFFS][constants.KEY__IMAGESETS__FIELD__BASE_URL]}}/{{imagePair[constants.KEY__IMAGEPAIRS__DIFFERENCES][constants.KEY__DIFFERENCES__WHITE_DIFF_URL]}}" target="_blank">View Image</a><br/> + <img ng-if="showThumbnails" + width="{{imageSize}}" + ng-src="{{imageSets[constants.KEY__IMAGESETS__SET__WHITEDIFFS][constants.KEY__IMAGESETS__FIELD__BASE_URL]}}/{{imagePair[constants.KEY__IMAGEPAIRS__DIFFERENCES][constants.KEY__DIFFERENCES__WHITE_DIFF_URL]}}" /> + <br/> + {{imagePair[constants.KEY__IMAGEPAIRS__DIFFERENCES][constants.KEY__DIFFERENCES__PERCENT_DIFF_PIXELS].toFixed(4)}}% + ({{imagePair[constants.KEY__IMAGEPAIRS__DIFFERENCES][constants.KEY__DIFFERENCES__NUM_DIFF_PIXELS]}}) + </div> + <div ng-show="!imagePair[constants.KEY__IMAGEPAIRS__IS_DIFFERENT]" + style="text-align:center"> + –none– + </div> + </td> + + <!-- diffs: per-channel RGB deltas --> + <td width="{{imageSize}}" ng-if="imagePair[constants.KEY__IMAGEPAIRS__ROWSPAN] > 0" rowspan="{{imagePair[constants.KEY__IMAGEPAIRS__ROWSPAN]}}"> + <div ng-if="imagePair[constants.KEY__IMAGEPAIRS__IS_DIFFERENT]" + title="Perceptual difference measure is {{imagePair[constants.KEY__IMAGEPAIRS__DIFFERENCES][constants.KEY__DIFFERENCES__PERCEPTUAL_DIFF].toFixed(4)}}%. Maximum difference per channel: R={{imagePair[constants.KEY__IMAGEPAIRS__DIFFERENCES][constants.KEY__DIFFERENCES__MAX_DIFF_PER_CHANNEL][0]}}, G={{imagePair[constants.KEY__IMAGEPAIRS__DIFFERENCES][constants.KEY__DIFFERENCES__MAX_DIFF_PER_CHANNEL][1]}}, B={{imagePair[constants.KEY__IMAGEPAIRS__DIFFERENCES][constants.KEY__DIFFERENCES__MAX_DIFF_PER_CHANNEL][2]}}"> + + <a href="{{imageSets[constants.KEY__IMAGESETS__SET__DIFFS][constants.KEY__IMAGESETS__FIELD__BASE_URL]}}/{{imagePair[constants.KEY__IMAGEPAIRS__DIFFERENCES][constants.KEY__DIFFERENCES__DIFF_URL]}}" target="_blank">View Image</a><br/> + <img ng-if="showThumbnails" + ng-style="{backgroundColor: pixelDiffBgColor}" + width="{{imageSize}}" + ng-src="{{imageSets[constants.KEY__IMAGESETS__SET__DIFFS][constants.KEY__IMAGESETS__FIELD__BASE_URL]}}/{{imagePair[constants.KEY__IMAGEPAIRS__DIFFERENCES][constants.KEY__DIFFERENCES__DIFF_URL]}}" /> + <br/> + {{imagePair[constants.KEY__IMAGEPAIRS__DIFFERENCES][constants.KEY__DIFFERENCES__PERCEPTUAL_DIFF].toFixed(4)}}% + {{imagePair[constants.KEY__IMAGEPAIRS__DIFFERENCES][constants.KEY__DIFFERENCES__MAX_DIFF_PER_CHANNEL]}} + </div> + <div ng-show="!imagePair[constants.KEY__IMAGEPAIRS__IS_DIFFERENT]" + style="text-align:center"> + –none– + </div> + </td> + + <td ng-if="imagePair[constants.KEY__IMAGEPAIRS__ROWSPAN] > 0" rowspan="{{imagePair[constants.KEY__IMAGEPAIRS__ROWSPAN]}}"> + <br/> + <input type="checkbox" + name="rowSelect" + value="{{imagePair.index}}" + ng-checked="isValueInArray(imagePair.index, selectedImagePairs)" + ng-click="toggleSomeImagePairs($index, imagePair[constants.KEY__IMAGEPAIRS__ROWSPAN])"> + </tr> + </table> <!-- imagePairs --> + </td></tr></table> <!-- table holding results header + imagePairs table --> + + </div><!-- main display area of selected tab --> + </div><!-- everything: hide until readyToDisplay --> + +</body> +</html> |