blob: 2f8241e0473896e96ef829150d6af9cd58666e31 [file] [log] [blame]
epoger0b712762014-08-05 10:07:22 -07001<!DOCTYPE html>
2
3<html ng-app="Loader" ng-controller="Loader.Controller">
4
5<head>
6 <title ng-bind="windowTitle"></title>
humper27ff2272014-08-06 12:39:59 -07007 <script src="//ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
stephanad9bf7db2014-08-08 07:21:00 -07008 <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.20/angular.js"></script>
epoger0b712762014-08-05 10:07:22 -07009 <script src="constants.js"></script>
10 <script src="live-loader.js"></script>
humper27ff2272014-08-06 12:39:59 -070011 <script src="utils.js"></script>
12
epoger0b712762014-08-05 10:07:22 -070013 <link rel="stylesheet" href="view.css">
14</head>
15
16<body>
17 <h2>
18 Instructions, roadmap, etc. are at
19 <a href="http://tinyurl.com/SkiaRebaselineServer">
20 http://tinyurl.com/SkiaRebaselineServer
21 </a>
22 </h2>
23
24 <em ng-show="!readyToDisplay">
25 Loading results of query:
26 <ul>
epogere73cd5a2014-08-07 12:13:12 -070027 <li>setA: "{{setASection}}" within {{setADir}}</li>
28 <li>setB: "{{setBSection}}" within {{setBDir}}</li>
epoger0b712762014-08-05 10:07:22 -070029 </ul>
30 <br>
31 {{loadingMessage}}
32 </em>
33
34 <div ng-show="readyToDisplay">
35
36 <div class="warning-div"
37 ng-show="urlSchemaVersionLoaded != constants.URL_VALUE__SCHEMA_VERSION__CURRENT">
38 WARNING! The URL you loaded used schema version {{urlSchemaVersionLoaded}}, rather than
39 the most recent version {{constants.URL_VALUE__SCHEMA_VERSION__CURRENT}}. It has been
40 converted to the most recent version on a best-effort basis; you may wish to double-check
41 which records are displayed.
42 </div>
43
44 <div class="warning-div"
45 ng-show="header[constants.KEY__HEADER__IS_EDITABLE] && header[constants.KEY__HEADER__IS_EXPORTED]">
46 WARNING! These results are editable and exported, so any user
47 who can connect to this server over the network can modify them.
48 </div>
49
50 <div ng-show="header[constants.KEY__HEADER__TIME_UPDATED]">
epogere73cd5a2014-08-07 12:13:12 -070051 setA: "{{setASection}}" within {{setADir}}<br>
52 setB: "{{setBSection}}" within {{setBDir}}<br>
epoger0b712762014-08-05 10:07:22 -070053 These results current as of
54 {{localTimeString(header[constants.KEY__HEADER__TIME_UPDATED])}}
55 </div>
56
57 <div class="tab-wrapper"><!-- tabs -->
58 <div class="tab-spacer" ng-repeat="tab in tabs">
59 <div class="tab tab-{{tab == viewingTab}}"
60 ng-click="setViewingTab(tab)">
61 &nbsp;{{tab}} ({{numResultsPerTab[tab]}})&nbsp;
62 </div>
63 <div class="tab-spacer">
64 &nbsp;
65 </div>
66 </div>
67 </div><!-- tabs -->
68
69 <div class="tab-main"><!-- main display area of selected tab -->
70
71 <br>
72 <!-- We only show the filters/settings table on the Unfiled tab. -->
73 <table ng-show="viewingTab == defaultTab" border="1">
74 <tr>
75 <th colspan="4">
76 Filters
77 </th>
78 <th>
79 Settings
80 </th>
81 </tr>
82 <tr valign="top">
83
84 <!-- filters -->
85 <td ng-repeat="columnName in orderedColumnNames">
86
87 <!-- Only display filterable columns here... -->
88 <div ng-if="extraColumnHeaders[columnName][constants.KEY__EXTRACOLUMNHEADERS__IS_FILTERABLE]">
89 {{extraColumnHeaders[columnName][constants.KEY__EXTRACOLUMNHEADERS__HEADER_TEXT]}}<br>
90
91 <!-- If we filter this column using free-form text match... -->
92 <div ng-if="extraColumnHeaders[columnName][constants.KEY__EXTRACOLUMNHEADERS__USE_FREEFORM_FILTER]">
93 <input type="text"
94 ng-model="columnStringMatch[columnName]"
95 ng-change="setUpdatesPending(true)"/>
96 <br>
97 <button ng-click="setColumnStringMatch(columnName, '')"
98 ng-disabled="('' == columnStringMatch[columnName])">
99 clear (show all)
100 </button>
101 </div>
102
103 <!-- If we filter this column using checkboxes... -->
104 <div ng-if="!extraColumnHeaders[columnName][constants.KEY__EXTRACOLUMNHEADERS__USE_FREEFORM_FILTER]">
105 <label ng-repeat="valueAndCount in extraColumnHeaders[columnName][constants.KEY__EXTRACOLUMNHEADERS__VALUES_AND_COUNTS]">
106 <input type="checkbox"
107 name="resultTypes"
108 value="{{valueAndCount[0]}}"
109 ng-checked="isValueInSet(valueAndCount[0], showingColumnValues[columnName])"
110 ng-click="toggleValueInSet(valueAndCount[0], showingColumnValues[columnName]); setUpdatesPending(true)">
111 {{valueAndCount[0]}} ({{valueAndCount[1]}})<br>
112 </label>
113 <button ng-click="showingColumnValues[columnName] = {}; toggleValuesInSet(allColumnValues[columnName], showingColumnValues[columnName]); updateResults()"
114 ng-disabled="!readyToDisplay || allColumnValues[columnName].length == setSize(showingColumnValues[columnName])">
115 all
116 </button>
117 <button ng-click="showingColumnValues[columnName] = {}; updateResults()"
118 ng-disabled="!readyToDisplay || 0 == setSize(showingColumnValues[columnName])">
119 none
120 </button>
121 <button ng-click="toggleValuesInSet(allColumnValues[columnName], showingColumnValues[columnName]); updateResults()">
122 toggle
123 </button>
124 </div>
125
126 </div>
127 </td>
128
129 <!-- settings -->
130 <td><table>
131 <tr><td>
132 <input type="checkbox" ng-model="showThumbnailsPending"
133 ng-init="showThumbnailsPending = true"
134 ng-change="areUpdatesPending = true"/>
135 Show thumbnails
136 </td></tr>
137 <tr><td>
138 <input type="checkbox" ng-model="mergeIdenticalRowsPending"
139 ng-init="mergeIdenticalRowsPending = true"
140 ng-change="areUpdatesPending = true"/>
141 Merge identical rows
142 </td></tr>
143 <tr><td>
144 Image width
145 <input type="text" ng-model="imageSizePending"
146 ng-init="imageSizePending=100"
147 ng-change="areUpdatesPending = true"
148 maxlength="4"/>
149 </td></tr>
150 <tr><td>
151 Max records to display
152 <input type="text" ng-model="displayLimitPending"
153 ng-init="displayLimitPending=50"
154 ng-change="areUpdatesPending = true"
155 maxlength="4"/>
156 </td></tr>
157 <tr><td>
158 <button class="update-results-button"
159 ng-click="updateResults()"
160 ng-disabled="!areUpdatesPending">
161 Update Results
162 </button>
163 </td></tr>
164 </tr></table></td>
165 </tr>
166 </table>
167
168 <p>
169
170 <!-- Submission UI that we only show in the Pending Approval tab. -->
171 <div ng-show="'Pending Approval' == viewingTab">
172 <div style="display:inline-block">
173 <button style="font-size:20px"
174 ng-click="submitApprovals(filteredImagePairs)"
175 ng-disabled="submitPending || (filteredImagePairs.length == 0)">
176 Update these {{filteredImagePairs.length}} expectations on the server
177 </button>
178 </div>
179 <div style="display:inline-block">
180 <div style="font-size:20px"
181 ng-show="submitPending">
182 Submitting, please wait...
183 </div>
184 </div>
185 <div>
186 Advanced settings...
187 <input type="checkbox" ng-model="showSubmitAdvancedSettings">
188 show
189 <ul ng-show="showSubmitAdvancedSettings">
190 <li ng-repeat="setting in [constants.KEY__EXPECTATIONS__REVIEWED, constants.KEY__EXPECTATIONS__IGNOREFAILURE]">
191 {{setting}}
192 <input type="checkbox" ng-model="submitAdvancedSettings[setting]">
193 </li>
194 <li ng-repeat="setting in ['bug']">
195 {{setting}}
196 <input type="text" ng-model="submitAdvancedSettings[setting]">
197 </li>
198 </ul>
199 </div>
200 </div>
201
202 <p>
203
204 <table border="0"><tr><td> <!-- table holding results header + results table -->
205 <table border="0" width="100%"> <!-- results header -->
206 <tr>
207 <td>
208 Found {{filteredImagePairs.length}} matches;
209 <span ng-show="filteredImagePairs.length > limitedImagePairs.length">
210 displaying the first {{limitedImagePairs.length}}.
211 </span>
212 <span ng-show="filteredImagePairs.length <= limitedImagePairs.length">
213 displaying them all.
214 </span>
215 <span ng-show="renderEndTime > renderStartTime">
216 Rendered in {{(renderEndTime - renderStartTime).toFixed(0)}} ms.
217 </span>
218 <br>
219 (click on the column header radio buttons to re-sort by that column)
220 </td>
221 <td align="right">
222 <div>
223 all tests shown:
224 <button ng-click="selectAllImagePairs()">
225 select
226 </button>
227 <button ng-click="clearAllImagePairs()">
228 clear
229 </button>
230 <button ng-click="toggleAllImagePairs()">
231 toggle
232 </button>
233 </div>
234 <div ng-repeat="otherTab in tabs">
235 <button ng-click="moveSelectedImagePairsToTab(otherTab)"
236 ng-disabled="selectedImagePairs.length == 0"
237 ng-show="otherTab != viewingTab">
238 move {{selectedImagePairs.length}} selected tests to {{otherTab}} tab
239 </button>
240 </div>
241 </td>
242 </tr>
243 </table> <!-- results header -->
244 </td></tr><tr><td>
245 <table border="1" ng-app="diff_viewer"> <!-- results -->
246 <tr>
247 <!-- Most column headers are displayed in a common fashion... -->
248 <th ng-repeat="columnName in orderedColumnNames">
stephanad9bf7db2014-08-08 07:21:00 -0700249 <a ng-class="'sort-' + sortedByColumnsCls(columnName)"
250 ng-click="sortResultsBy(constants.KEY__IMAGEPAIRS__EXTRACOLUMNS, columnName)"
251 href=""
252 class="sortable-header">
253 {{extraColumnHeaders[columnName][constants.KEY__EXTRACOLUMNHEADERS__HEADER_TEXT]}}
254 </a>
epoger0b712762014-08-05 10:07:22 -0700255 </th>
256 <!-- ... but there are a few columns where we display things differently. -->
257 <th>
stephanad9bf7db2014-08-08 07:21:00 -0700258 <a ng-class="'sort-' + sortedByColumnsCls(constants.KEY__EXPECTATIONS__BUGS)"
259 ng-click="sortResultsBy(constants.KEY__IMAGEPAIRS__EXPECTATIONS, constants.KEY__EXPECTATIONS__BUGS)"
260 href=""
261 class="sortable-header">
262 bugs
263 </a>
epoger0b712762014-08-05 10:07:22 -0700264 bugs
265 </th>
266 <th width="{{imageSize}}">
stephanad9bf7db2014-08-08 07:21:00 -0700267 <a ng-class="'sort-' + sortedByColumnsCls(constants.KEY__IMAGEPAIRS__IMAGE_A_URL)"
268 ng-click="sortResultsBy('none', constants.KEY__IMAGEPAIRS__IMAGE_A_URL)"
269 href=""
270 class="sortable-header">
271 {{imageSets[constants.KEY__IMAGESETS__SET__IMAGE_A][constants.KEY__IMAGESETS__FIELD__DESCRIPTION]}}
272 </a>
epoger0b712762014-08-05 10:07:22 -0700273 </th>
274 <th width="{{imageSize}}">
stephanad9bf7db2014-08-08 07:21:00 -0700275 <a ng-class="'sort-' + sortedByColumnsCls(constants.KEY__IMAGEPAIRS__IMAGE_B_URL)"
276 ng-click="sortResultsBy('none', constants.KEY__IMAGEPAIRS__IMAGE_B_URL)"
277 href=""
278 class="sortable-header">
279 {{imageSets[constants.KEY__IMAGESETS__SET__IMAGE_B][constants.KEY__IMAGESETS__FIELD__DESCRIPTION]}}
280 </a>
epoger0b712762014-08-05 10:07:22 -0700281 </th>
282 <th width="{{imageSize}}">
stephanad9bf7db2014-08-08 07:21:00 -0700283 <a ng-class="'sort-' + sortedByColumnsCls(constants.KEY__DIFFERENCES__PERCENT_DIFF_PIXELS)"
284 ng-click="sortResultsBy(constants.KEY__IMAGEPAIRS__DIFFERENCES, constants.KEY__DIFFERENCES__PERCENT_DIFF_PIXELS)"
285 href=""
286 class="sortable-header">
287 differing pixels in white
288 </a>
epoger0b712762014-08-05 10:07:22 -0700289 </th>
290 <th width="{{imageSize}}">
stephanad9bf7db2014-08-08 07:21:00 -0700291 <a ng-class="'sort-' + sortedByColumnsCls(constants.KEY__DIFFERENCES__PERCEPTUAL_DIFF)"
292 ng-click="sortResultsBy(constants.KEY__IMAGEPAIRS__DIFFERENCES, constants.KEY__DIFFERENCES__PERCEPTUAL_DIFF)"
293 href=""
294 class="sortable-header">
295 perceptual difference
296 </a>
epoger0b712762014-08-05 10:07:22 -0700297 <br>
298 <input type="range" ng-model="pixelDiffBgColorBrightness"
299 ng-init="pixelDiffBgColorBrightness=64; pixelDiffBgColor=brightnessStringToHexColor(pixelDiffBgColorBrightness)"
300 ng-change="pixelDiffBgColor=brightnessStringToHexColor(pixelDiffBgColorBrightness)"
301 title="image background brightness"
302 min="0" max="255"/>
303 </th>
304 <th>
305 <!-- imagepair-selection checkbox column -->
306 </th>
307 </tr>
308
309 <tr ng-repeat="imagePair in limitedImagePairs" valign="top"
310 ng-class-odd="'results-odd'" ng-class-even="'results-even'"
311 results-updated-callback-directive>
312
313 <td ng-repeat="columnName in orderedColumnNames">
314 {{imagePair[constants.KEY__IMAGEPAIRS__EXTRACOLUMNS][columnName]}}
315 <br>
316 <button class="show-only-button"
317 ng-show="viewingTab == defaultTab"
318 ng-disabled="1 == setSize(showingColumnValues[columnName])"
319 ng-click="showOnlyColumnValue(columnName, imagePair[constants.KEY__IMAGEPAIRS__EXTRACOLUMNS][columnName])"
320 title="show only results of {{extraColumnHeaders[columnName][constants.KEY__EXTRACOLUMNHEADERS__HEADER_TEXT]}} {{imagePair[constants.KEY__IMAGEPAIRS__EXTRACOLUMNS][columnName]}}">
321 show only
322 </button>
323 <br>
324 <button class="show-all-button"
325 ng-show="viewingTab == defaultTab"
326 ng-disabled="allColumnValues[columnName].length == setSize(showingColumnValues[columnName])"
327 ng-click="showAllColumnValues(columnName)"
328 title="show results of all {{extraColumnHeaders[columnName][constants.KEY__EXTRACOLUMNHEADERS__HEADER_TEXT]}}s">
329 show all
330 </button>
331 </td>
332
333 <!-- bugs -->
334 <td>
335 <a ng-repeat="bug in imagePair[constants.KEY__IMAGEPAIRS__EXPECTATIONS][constants.KEY__EXPECTATIONS__BUGS]"
336 href="https://code.google.com/p/skia/issues/detail?id={{bug}}"
337 target="_blank">
338 {{bug}}
339 </a>
340 </td>
341
342 <!-- image A -->
343 <td width="{{imageSize}}" ng-if="imagePair[constants.KEY__IMAGEPAIRS__ROWSPAN] > 0" rowspan="{{imagePair[constants.KEY__IMAGEPAIRS__ROWSPAN]}}">
344 <div ng-if="imagePair[constants.KEY__IMAGEPAIRS__IMAGE_A_URL] != null">
345 <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/>
346 <img ng-if="showThumbnails"
347 width="{{imageSize}}"
348 ng-src="{{imageSets[constants.KEY__IMAGESETS__SET__IMAGE_A][constants.KEY__IMAGESETS__FIELD__BASE_URL]}}/{{imagePair[constants.KEY__IMAGEPAIRS__IMAGE_A_URL]}}" />
349 </div>
350 <div ng-show="imagePair[constants.KEY__IMAGEPAIRS__IMAGE_A_URL] == null"
351 style="text-align:center">
352 &ndash;none&ndash;
353 </div>
354 </td>
355
356 <!-- image B -->
357 <td width="{{imageSize}}" ng-if="imagePair[constants.KEY__IMAGEPAIRS__ROWSPAN] > 0" rowspan="{{imagePair[constants.KEY__IMAGEPAIRS__ROWSPAN]}}">
358 <div ng-if="imagePair[constants.KEY__IMAGEPAIRS__IMAGE_B_URL] != null">
359 <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/>
360 <img ng-if="showThumbnails"
361 width="{{imageSize}}"
362 ng-src="{{imageSets[constants.KEY__IMAGESETS__SET__IMAGE_B][constants.KEY__IMAGESETS__FIELD__BASE_URL]}}/{{imagePair[constants.KEY__IMAGEPAIRS__IMAGE_B_URL]}}" />
363 </div>
364 <div ng-show="imagePair[constants.KEY__IMAGEPAIRS__IMAGE_B_URL] == null"
365 style="text-align:center">
366 &ndash;none&ndash;
367 </div>
368 </td>
369
370 <!-- whitediffs: every differing pixel shown in white -->
371 <td width="{{imageSize}}" ng-if="imagePair[constants.KEY__IMAGEPAIRS__ROWSPAN] > 0" rowspan="{{imagePair[constants.KEY__IMAGEPAIRS__ROWSPAN]}}">
372 <div ng-if="imagePair[constants.KEY__IMAGEPAIRS__IS_DIFFERENT]"
373 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.">
374
375 <a href="{{imageSets[constants.KEY__IMAGESETS__SET__WHITEDIFFS][constants.KEY__IMAGESETS__FIELD__BASE_URL]}}/{{getImageDiffRelativeUrl(imagePair)}}" target="_blank">View Image</a><br/>
376 <img ng-if="showThumbnails"
377 width="{{imageSize}}"
378 ng-src="{{imageSets[constants.KEY__IMAGESETS__SET__WHITEDIFFS][constants.KEY__IMAGESETS__FIELD__BASE_URL]}}/{{getImageDiffRelativeUrl(imagePair)}}" />
379 <br/>
380 {{imagePair[constants.KEY__IMAGEPAIRS__DIFFERENCES][constants.KEY__DIFFERENCES__PERCENT_DIFF_PIXELS].toFixed(4)}}%
381 ({{imagePair[constants.KEY__IMAGEPAIRS__DIFFERENCES][constants.KEY__DIFFERENCES__NUM_DIFF_PIXELS]}})
382 </div>
383 <div ng-show="!imagePair[constants.KEY__IMAGEPAIRS__IS_DIFFERENT]"
384 style="text-align:center">
385 &ndash;none&ndash;
386 </div>
387 </td>
388
389 <!-- diffs: per-channel RGB deltas -->
390 <td width="{{imageSize}}" ng-if="imagePair[constants.KEY__IMAGEPAIRS__ROWSPAN] > 0" rowspan="{{imagePair[constants.KEY__IMAGEPAIRS__ROWSPAN]}}">
391 <div ng-if="imagePair[constants.KEY__IMAGEPAIRS__IS_DIFFERENT]"
392 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]}}">
393
394 <a href="{{imageSets[constants.KEY__IMAGESETS__SET__DIFFS][constants.KEY__IMAGESETS__FIELD__BASE_URL]}}/{{getImageDiffRelativeUrl(imagePair)}}" target="_blank">View Image</a><br/>
395 <img ng-if="showThumbnails"
396 ng-style="{backgroundColor: pixelDiffBgColor}"
397 width="{{imageSize}}"
398 ng-src="{{imageSets[constants.KEY__IMAGESETS__SET__DIFFS][constants.KEY__IMAGESETS__FIELD__BASE_URL]}}/{{getImageDiffRelativeUrl(imagePair)}}" />
399 <br/>
400 {{imagePair[constants.KEY__IMAGEPAIRS__DIFFERENCES][constants.KEY__DIFFERENCES__PERCEPTUAL_DIFF].toFixed(4)}}%
401 {{imagePair[constants.KEY__IMAGEPAIRS__DIFFERENCES][constants.KEY__DIFFERENCES__MAX_DIFF_PER_CHANNEL]}}
402 </div>
403 <div ng-show="!imagePair[constants.KEY__IMAGEPAIRS__IS_DIFFERENT]"
404 style="text-align:center">
405 &ndash;none&ndash;
406 </div>
407 </td>
408
409 <td ng-if="imagePair[constants.KEY__IMAGEPAIRS__ROWSPAN] > 0" rowspan="{{imagePair[constants.KEY__IMAGEPAIRS__ROWSPAN]}}">
410 <br/>
411 <input type="checkbox"
412 name="rowSelect"
413 value="{{imagePair.index}}"
414 ng-checked="isValueInArray(imagePair.index, selectedImagePairs)"
415 ng-click="toggleSomeImagePairs($index, imagePair[constants.KEY__IMAGEPAIRS__ROWSPAN])">
416 </tr>
417 </table> <!-- imagePairs -->
418 </td></tr></table> <!-- table holding results header + imagePairs table -->
419
420 </div><!-- main display area of selected tab -->
421 </div><!-- everything: hide until readyToDisplay -->
422
423</body>
424</html>